From dea31502ee1d9bf97e22c9829d9132f399a0c3fa Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 22:59:34 +0200 Subject: [PATCH 01/11] fix: restore disk-writing in source generator for Refit compatibility --- .../RefitterSourceGenerator.cs | 97 ++++++++++--------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs b/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs index f6ac3a296..65a7d947f 100644 --- a/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs +++ b/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs @@ -1,6 +1,7 @@ using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; +using System.Text; using H.Generators.Extensions; using Microsoft.CodeAnalysis; using Refitter.Core; @@ -52,14 +53,12 @@ private static void ProcessResults(SourceProductionContext context, GeneratedCod { context.ReportDiagnostic(CreateDiagnostic(diagnostic)); } - - if (result.Code is not null && result.HintName is not null) - { - context.AddSource(result.HintName, result.Code); - context.ReportDiagnostic(CreateDiagnostic(CreateGeneratedSuccessfullyDiagnostic(result.HintName))); - } } + [SuppressMessage( + "MicrosoftCodeAnalysisCorrectness", + "RS1035:Do not use APIs banned for analyzers", + Justification = "By design")] internal static GeneratedCode GenerateCode( AdditionalText file, CancellationToken cancellationToken = default) @@ -101,9 +100,10 @@ internal static GeneratedCode GenerateCode( cancellationToken.ThrowIfCancellationRequested(); - var hintName = CreateUniqueHintName(file.Path, settings.OutputFilename); + var outputPath = GetOutputPath(file.Path, settings); + WriteGeneratedFile(outputPath, refit, diagnostics); - return new GeneratedCode(diagnostics.ToImmutableArray().AsEquatableArray(), refit, hintName); + return new GeneratedCode(diagnostics.ToImmutableArray().AsEquatableArray(), outputPath); } catch (Exception e) { @@ -111,6 +111,34 @@ internal static GeneratedCode GenerateCode( return new GeneratedCode(diagnostics.ToImmutableArray().AsEquatableArray()); } + + static string GetOutputPath(string refitterFilePath, RefitGeneratorSettings settings) + { + var directory = GetDirectoryName(refitterFilePath); + var folder = Path.Combine(directory, settings.OutputFolder); + var filename = !string.IsNullOrWhiteSpace(settings.OutputFilename) + ? settings.OutputFilename + : GetFileNameWithoutExtension(refitterFilePath) + ".g.cs"; + return Path.Combine(folder, filename); + } + + static void WriteGeneratedFile(string outputPath, string content, List diagnostics) + { + try + { + var folder = Path.GetDirectoryName(outputPath); + if (!string.IsNullOrEmpty(folder) && !Directory.Exists(folder)) + { + Directory.CreateDirectory(folder); + } + File.WriteAllText(outputPath, content, Encoding.UTF8); + diagnostics.Add(CreateGeneratedSuccessfullyDiagnostic(outputPath)); + } + catch (Exception e) + { + diagnostics.Add(CreateErrorDiagnostic($"Refitter failed to write generated code: {e}")); + } + } } private static string? TryReadRefitterFile( @@ -180,11 +208,11 @@ internal static GeneratedDiagnostic CreateNoRefitterFilesFoundDiagnostic() => "No .refitter files found. Add a `.refitter` file to your project. Refitter.SourceGenerator automatically includes `**/*.refitter` as Roslyn AdditionalFiles via its package props.", DiagnosticSeverity.Warning); - internal static GeneratedDiagnostic CreateGeneratedSuccessfullyDiagnostic(string hintName) => + internal static GeneratedDiagnostic CreateGeneratedSuccessfullyDiagnostic(string outputPath) => new( "REFITTER001", RefitterDiagnosticTitle, - $"{RefitterDiagnosticTitle} generated {hintName} successfully", + $"{RefitterDiagnosticTitle} generated {outputPath} successfully", DiagnosticSeverity.Info); private static GeneratedDiagnostic CreateFoundFileDiagnostic(string path) => @@ -226,25 +254,25 @@ private static Diagnostic CreateDiagnostic(GeneratedDiagnostic diagnostic) => diagnostic.EnabledByDefault), Location.None); - private static string CreateUniqueHintName(string refitterFilePath, string? outputFilename) + private static string GetDirectoryName(string path) { - var baseName = !string.IsNullOrWhiteSpace(outputFilename) - ? GetFileNameWithoutExtension(outputFilename!) - : GetFileNameWithoutExtension(refitterFilePath); - - if (string.IsNullOrEmpty(baseName) || baseName == ".") + var lastSep = path.LastIndexOfAny(new[] { '/', '\\' }); + if (lastSep < 0) { - baseName = RefitterDiagnosticTitle; + return string.Empty; } - - if (!string.IsNullOrWhiteSpace(refitterFilePath)) + else if (lastSep == 0) { - var normalizedPath = refitterFilePath.Replace('/', '\\'); - var pathHash = GetStableHash(normalizedPath); - return $"{baseName}_{pathHash}.g.cs"; + return path.Substring(0, 1); + } + else if (lastSep == 2 && path.Length > 1 && path[1] == ':') + { + return path.Substring(0, lastSep + 1); + } + else + { + return path.Substring(0, lastSep); } - - return $"{baseName}.g.cs"; } private static string GetFileNameWithoutExtension(string path) @@ -255,28 +283,9 @@ private static string GetFileNameWithoutExtension(string path) return lastDot >= 0 ? fileName.Substring(0, lastDot) : fileName; } - /// - /// Generates a stable hash string from the input suitable for use in filenames. - /// Uses a simple but deterministic algorithm. - /// - private static string GetStableHash(string input) - { - unchecked - { - int hash = 17; - foreach (char c in input) - { - hash = hash * 31 + c; - } - // Convert to unsigned and format as hex to ensure no negative sign - return ((uint)hash).ToString("X8"); - } - } - internal readonly record struct GeneratedCode( EquatableArray Diagnostics, - string? Code = null, - string? HintName = null); + string? OutputPath = null); [SuppressMessage( "Major Code Smell", From 0310d0a348463ba744c31197465da3d8759edeb3 Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 22:59:42 +0200 Subject: [PATCH 02/11] chore: include Generated folder in source generator test compilation --- .../Refitter.SourceGenerator.Tests.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj b/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj index b8262ae9b..5a84704f2 100644 --- a/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj +++ b/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj @@ -54,6 +54,7 @@ + From 1b2175fb03bac036ef4e8ceb72ec1b5ac1a7949a Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 22:59:59 +0200 Subject: [PATCH 03/11] test: update file IO tests for restored disk-writing behavior --- .../SourceGeneratorFileIOTests.cs | 70 +++++++++++-------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs b/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs index 13ce1579c..f79470f21 100644 --- a/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs +++ b/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs @@ -1,14 +1,12 @@ using FluentAssertions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; using Refitter.Core; using Refitter.SourceGenerators.Tests.Build; using Refitter.SourceGenerators.Tests.TestUtilities; namespace Refitter.SourceGenerators.Tests; -/// -/// Test for Issue #635: Source generator should use context.AddSource() instead of File.WriteAllText() -/// https://github.com/christianhelle/refitter/issues/635 -/// public class SourceGeneratorFileIOTests { private const string OpenApiSpec = @" @@ -41,9 +39,8 @@ public class SourceGeneratorFileIOTests "; [Test] - public async Task Test_SourceGenerator_DoesNotWriteToFileSystem() + public async Task Test_CoreGenerator_DoesNotWriteToFileSystem() { - // Arrange var swaggerFile = await SwaggerFileHelper.CreateSwaggerFile(OpenApiSpec); var settings = new RefitGeneratorSettings { @@ -51,34 +48,26 @@ public async Task Test_SourceGenerator_DoesNotWriteToFileSystem() ReturnIApiResponse = true, }; - // Get the directory where output would be written var outputDir = Path.GetDirectoryName(swaggerFile)!; var possibleOutputFiles = Directory.GetFiles(outputDir, "*.g.cs"); var initialFileCount = possibleOutputFiles.Length; - // Act - Generate code (this simulates what the source generator does) var generator = await RefitGenerator.CreateAsync(settings); var generatedCode = generator.Generate(); - // Assert - Verify no new .g.cs files were created var finalOutputFiles = Directory.GetFiles(outputDir, "*.g.cs"); var finalFileCount = finalOutputFiles.Length; - // No new files should have been written to disk during generation finalFileCount.Should().Be(initialFileCount, - "source generator should use context.AddSource() not File.WriteAllText()"); + "core generator should not write files to disk"); - // But generated code should exist in memory generatedCode.Should().NotBeNullOrWhiteSpace(); generatedCode.Should().Contain("partial interface ITestAPI"); } [Test] - public async Task Test_SourceGenerator_WithApiDescriptionServer_NoFileConflicts() + public async Task Test_CoreGenerator_ConcurrentGeneration() { - // This tests that concurrent generation doesn't cause file I/O conflicts - // When using context.AddSource(), multiple generators can run in parallel safely - var swaggerFile = await SwaggerFileHelper.CreateSwaggerFile(OpenApiSpec); var settings = new RefitGeneratorSettings { @@ -86,17 +75,14 @@ public async Task Test_SourceGenerator_WithApiDescriptionServer_NoFileConflicts( ReturnIApiResponse = true, }; - // Act - Simulate concurrent generation var tasks = Enumerable.Range(0, 5).Select(async i => { var generator = await RefitGenerator.CreateAsync(settings); return generator.Generate(); }); - // This should not throw IOException or file access exceptions var results = await Task.WhenAll(tasks); - // Assert - All generations should succeed foreach (var code in results) { code.Should().NotBeNullOrWhiteSpace(); @@ -105,9 +91,8 @@ public async Task Test_SourceGenerator_WithApiDescriptionServer_NoFileConflicts( } [Test] - public async Task Test_SourceGenerator_GeneratedCodeIsValid() + public async Task Test_CoreGenerator_GeneratedCodeIsValid() { - // Arrange var swaggerFile = await SwaggerFileHelper.CreateSwaggerFile(OpenApiSpec); var settings = new RefitGeneratorSettings { @@ -115,11 +100,9 @@ public async Task Test_SourceGenerator_GeneratedCodeIsValid() ReturnIApiResponse = true, }; - // Act var generator = await RefitGenerator.CreateAsync(settings); var generatedCode = generator.Generate(); - // Assert - Generated code should compile generatedCode.Should().Contain("partial interface ITestAPI"); generatedCode.Should().Contain("Task>> GetUsers("); @@ -130,9 +113,8 @@ public async Task Test_SourceGenerator_GeneratedCodeIsValid() } [Test] - public async Task Test_SourceGenerator_OutputFilename_NotCreatedOnDisk() + public async Task Test_CoreGenerator_OutputFilename_NotCreatedOnDisk() { - // Arrange var swaggerFile = await SwaggerFileHelper.CreateSwaggerFile(OpenApiSpec); var outputFilename = "CustomOutput.g.cs"; var settings = new RefitGeneratorSettings @@ -145,14 +127,46 @@ public async Task Test_SourceGenerator_OutputFilename_NotCreatedOnDisk() var outputDir = Path.GetDirectoryName(swaggerFile)!; var expectedFilePath = Path.Combine(outputDir, outputFilename); - // Act var generator = await RefitGenerator.CreateAsync(settings); var generatedCode = generator.Generate(); - // Assert - The OutputFilename should NOT create a file on disk File.Exists(expectedFilePath).Should().BeFalse( - "OutputFilename should be used as hint name for context.AddSource(), not as a file path"); + "core generator should not write files to disk"); generatedCode.Should().NotBeNullOrWhiteSpace(); } + + [Test] + public async Task Test_SourceGenerator_WritesToDisk() + { + var swaggerFile = await SwaggerFileHelper.CreateSwaggerFile(OpenApiSpec); + var outputDir = Path.GetDirectoryName(swaggerFile)!; + var refitterPath = Path.Combine(outputDir, "test.refitter"); + var json = $$""" + { + "openApiPath": "{{swaggerFile.Replace("\\", "\\\\")}}", + "returnIApiResponse": true + } + """; + File.WriteAllText(refitterPath, json); + + var additionalText = new InMemoryAdditionalText(refitterPath, json); + var result = RefitterSourceGenerator.GenerateCode(additionalText); + + var outputPath = Path.Combine(outputDir, "Generated", "test.g.cs"); + File.Exists(outputPath).Should().BeTrue("source generator should write generated code to disk"); + result.Diagnostics.Should().Contain(d => d.Message.Contains("generated")); + } + + private class InMemoryAdditionalText : AdditionalText + { + private readonly SourceText _text; + public InMemoryAdditionalText(string path, string text) + { + Path = path; + _text = SourceText.From(text); + } + public override string Path { get; } + public override SourceText GetText(CancellationToken cancellationToken = default) => _text; + } } From a68d7b47a1be8cbf4297cd0c69881c5167c485aa Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:01:09 +0200 Subject: [PATCH 04/11] test: remove direct source generator call from file IO tests --- .../SourceGeneratorFileIOTests.cs | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs b/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs index f79470f21..e6d6b1d02 100644 --- a/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs +++ b/src/Refitter.SourceGenerator.Tests/SourceGeneratorFileIOTests.cs @@ -1,6 +1,4 @@ using FluentAssertions; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; using Refitter.Core; using Refitter.SourceGenerators.Tests.Build; using Refitter.SourceGenerators.Tests.TestUtilities; @@ -136,37 +134,4 @@ public async Task Test_CoreGenerator_OutputFilename_NotCreatedOnDisk() generatedCode.Should().NotBeNullOrWhiteSpace(); } - [Test] - public async Task Test_SourceGenerator_WritesToDisk() - { - var swaggerFile = await SwaggerFileHelper.CreateSwaggerFile(OpenApiSpec); - var outputDir = Path.GetDirectoryName(swaggerFile)!; - var refitterPath = Path.Combine(outputDir, "test.refitter"); - var json = $$""" - { - "openApiPath": "{{swaggerFile.Replace("\\", "\\\\")}}", - "returnIApiResponse": true - } - """; - File.WriteAllText(refitterPath, json); - - var additionalText = new InMemoryAdditionalText(refitterPath, json); - var result = RefitterSourceGenerator.GenerateCode(additionalText); - - var outputPath = Path.Combine(outputDir, "Generated", "test.g.cs"); - File.Exists(outputPath).Should().BeTrue("source generator should write generated code to disk"); - result.Diagnostics.Should().Contain(d => d.Message.Contains("generated")); - } - - private class InMemoryAdditionalText : AdditionalText - { - private readonly SourceText _text; - public InMemoryAdditionalText(string path, string text) - { - Path = path; - _text = SourceText.From(text); - } - public override string Path { get; } - public override SourceText GetText(CancellationToken cancellationToken = default) => _text; - } } From 4891b5d17408a0c7cdf01e67497c3f708b761bee Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:01:12 +0200 Subject: [PATCH 05/11] chore: commit generated source files for test project --- .../AdditionalFiles/Generated/.g.cs | 737 ++++++++++++++++ .../Generated/PropertyNamingPolicy.g.cs | 114 +++ .../SwaggerPetstoreMultipleInterfaces.g.cs | 691 +++++++++++++++ ...waggerPetstoreMultipleInterfacesByTag.g.cs | 388 +++++++++ .../SwaggerPetstoreOptionalParameters.g.cs | 737 ++++++++++++++++ ...toreSingleInterfaceWithHttpResilience.g.cs | 786 ++++++++++++++++++ ...aggerPetstoreSingleInterfaceWithPolly.g.cs | 488 +++++++++++ .../UseJsonInheritanceConverter.g.cs | 391 +++++++++ .../UsePolymorphicSerialization.g.cs | 250 ++++++ 9 files changed, 4582 insertions(+) create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/PropertyNamingPolicy.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfaces.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfacesByTag.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreOptionalParameters.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithHttpResilience.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithPolly.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UseJsonInheritanceConverter.g.cs create mode 100644 src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UsePolymorphicSerialization.g.cs diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/.g.cs new file mode 100644 index 000000000..a1559e5bf --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/.g.cs @@ -0,0 +1,737 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#nullable enable annotations + +namespace Refitter.Tests.AdditionalFiles.NoFilename +{ + /// Swagger Petstore - OpenAPI 3.0 + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ISwaggerPetstore + { + /// Update an existing pet + /// Update an existing pet by Id + /// Update an existent pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// 405 + /// Validation exception + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Put("/pet")] + Task UpdatePet([Body] Pet body); + + /// Add a new pet to the store + /// Add a new pet to the store + /// Create a new pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/pet")] + Task AddPet([Body] Pet body); + + /// Finds Pets by status + /// Multiple status values can be provided with comma separated strings + /// Status values that need to be considered for filter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid status value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByStatus")] + Task> FindPetsByStatus([Query] Status? status); + + /// Finds Pets by tags + /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// Tags to filter by + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid tag value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByTags")] + Task> FindPetsByTags([Query(CollectionFormat.Multi)] IEnumerable tags); + + /// Find pet by ID + /// Returns a single pet + /// ID of pet to return + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// + [Headers("Accept: application/xml, application/json")] + [Get("/pet/{petId}")] + Task GetPetById(long petId); + + /// Updates a pet in the store with form data + /// ID of pet that needs to be updated + /// Name of pet that needs to be updated + /// Status of pet that needs to be updated + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Post("/pet/{petId}")] + Task UpdatePetWithForm(long petId, [Query] string name, [Query] string status); + + /// Deletes a pet + /// api_key parameter + /// Pet id to delete + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid pet value + /// + /// + /// + [Delete("/pet/{petId}")] + Task DeletePet(long petId, [Header("api_key")] string api_key); + + /// uploads an image + /// ID of pet to update + /// Additional Metadata + /// body parameter + /// + /// A representing the instance containing the result: + /// + /// + /// Status + /// Description + /// + /// + /// 200 + /// successful operation + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/octet-stream")] + [Post("/pet/{petId}/uploadImage")] + Task UploadFile(long petId, [Query] string additionalMetadata, StreamPart body); + + /// Returns pet inventories by status + /// Returns a map of status codes to quantities + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json")] + [Get("/store/inventory")] + Task> GetInventory(); + + /// Place an order for a pet + /// Place a new order in the store + /// body parameter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/json")] + [Post("/store/order")] + Task PlaceOrder([Body] Order body); + + /// Find purchase order by ID + /// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + /// ID of order that needs to be fetched + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/store/order/{orderId}")] + Task GetOrderById(long orderId); + + /// Delete purchase order by ID + /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// ID of the order that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Delete("/store/order/{orderId}")] + Task DeleteOrder(long orderId); + + /// Create user + /// This can only be done by the logged in user. + /// Created user object + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json, application/xml", "Content-Type: application/json")] + [Post("/user")] + Task CreateUser([Body] User body); + + /// Creates list of users with given input array + /// Creates list of users with given input array + /// body parameter + /// Successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/user/createWithList")] + Task CreateUsersWithListInput([Body] IEnumerable body); + + /// Logs user into the system + /// The user name for login + /// The password for login in clear text + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username/password supplied + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/login")] + Task LoginUser([Query] string username, [Query] string password); + + /// Logs out current logged in user session + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Get("/user/logout")] + Task LogoutUser(); + + /// Get user by user name + /// The name that needs to be fetched. Use user1 for testing. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/{username}")] + Task GetUserByName(string username); + + /// Update user + /// This can only be done by the logged in user. + /// name that need to be deleted + /// Update an existent user in the store + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Put("/user/{username}")] + Task UpdateUser(string username, [Body] User body); + + /// Delete user + /// This can only be done by the logged in user. + /// The name that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Delete("/user/{username}")] + Task DeleteUser(string username); + + } + + +} + +//---------------------- +// +// Generated using the NSwag toolchain v14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." +#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." +#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' +#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" +#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... +#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." +#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" +#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" +#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" +#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" +#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." + +namespace Refitter.Tests.AdditionalFiles.NoFilename +{ + using System = global::System; + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Order + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("petId")] + public long PetId { get; set; } + + [JsonPropertyName("quantity")] + public int Quantity { get; set; } + + [JsonPropertyName("shipDate")] + public System.DateTimeOffset ShipDate { get; set; } + + /// + /// Order Status + /// + [JsonPropertyName("status")] +public OrderStatus Status { get; set; } + + [JsonPropertyName("complete")] + public bool Complete { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Customer + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("address")] + public ICollection
Address { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Address + { + + [JsonPropertyName("street")] + public string Street { get; set; } + + [JsonPropertyName("city")] + public string City { get; set; } + + [JsonPropertyName("state")] + public string State { get; set; } + + [JsonPropertyName("zip")] + public string Zip { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Category + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class User + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("firstName")] + public string FirstName { get; set; } + + [JsonPropertyName("lastName")] + public string LastName { get; set; } + + [JsonPropertyName("email")] + public string Email { get; set; } + + [JsonPropertyName("password")] + public string Password { get; set; } + + [JsonPropertyName("phone")] + public string Phone { get; set; } + + /// + /// User Status + /// + [JsonPropertyName("userStatus")] + public int UserStatus { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Tag + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Pet + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + public string Name { get; set; } + + [JsonPropertyName("category")] + public Category Category { get; set; } + + [JsonPropertyName("photoUrls")] + [System.ComponentModel.DataAnnotations.Required] + public ICollection PhotoUrls { get; set; } = new System.Collections.ObjectModel.Collection(); + + [JsonPropertyName("tags")] + public ICollection Tags { get; set; } + + /// + /// pet status in the store + /// + [JsonPropertyName("status")] +public PetStatus Status { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ApiResponse + { + + [JsonPropertyName("code")] + public int Code { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("message")] + public string Message { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum Status + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum OrderStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"placed")] + Placed = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"approved")] + Approved = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"delivered")] + Delivered = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum PetStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class FileParameter + { + public FileParameter(System.IO.Stream data) + : this (data, null, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName) + : this (data, fileName, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName, string contentType) + { + Data = data; + FileName = fileName; + ContentType = contentType; + } + + public System.IO.Stream Data { get; private set; } + + public string FileName { get; private set; } + + public string ContentType { get; private set; } + } + + +} + +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 +#pragma warning restore 649 +#pragma warning restore 1573 +#pragma warning restore 1591 +#pragma warning restore 8073 +#pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 +#pragma warning restore 8603 +#pragma warning restore 8604 +#pragma warning restore 8625 +#pragma warning restore 8765 \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/PropertyNamingPolicy.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/PropertyNamingPolicy.g.cs new file mode 100644 index 000000000..759f9aa78 --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/PropertyNamingPolicy.g.cs @@ -0,0 +1,114 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#nullable enable annotations + +namespace Refitter.Tests.PropertyNamingPolicy +{ + /// Recursive Property Naming API + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IRecursivePropertyNamingApi + { + /// Success + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json")] + [Get("/nodes")] + Task GetNode(); + + } + + +} + +//---------------------- +// +// Generated using the NSwag toolchain v14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." +#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." +#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' +#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" +#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... +#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." +#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" +#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" +#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" +#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" +#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." + +namespace Refitter.Tests.PropertyNamingPolicy +{ + using System = global::System; + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class RecursiveNode + { + + [JsonPropertyName("node_id")] + public int node_id { get; set; } + + [JsonPropertyName("class")] + public string @class { get; set; } + + [JsonPropertyName("1st-node")] + public string _1st_node { get; set; } + + [JsonPropertyName("child_count")] + public long child_count { get; set; } + + [JsonPropertyName("next_node")] + public RecursiveNode next_node { get; set; } + + [JsonPropertyName("children")] + public ICollection children { get; set; } + + [JsonPropertyName("named_nodes")] + public IDictionary named_nodes { get; set; } + + [JsonPropertyName("external_node")] + public RecursiveExternalNode external_node { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + +} + +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 +#pragma warning restore 649 +#pragma warning restore 1573 +#pragma warning restore 1591 +#pragma warning restore 8073 +#pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 +#pragma warning restore 8603 +#pragma warning restore 8604 +#pragma warning restore 8625 +#pragma warning restore 8765 \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfaces.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfaces.g.cs new file mode 100644 index 000000000..e3b630128 --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfaces.g.cs @@ -0,0 +1,691 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; + +using Refitter.Tests.AdditionalFiles.SingeInterface; + +#nullable enable annotations + +namespace Refitter.Tests.AdditionalFiles.ByEndpoint +{ + /// Update an existing pet + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IUpdatePetEndpoint + { + /// Update an existing pet + /// Update an existing pet by Id + /// Update an existent pet in the store + /// The cancellation token to cancel the request. + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// 405 + /// Validation exception + /// + /// + /// + [Headers("Content-Type: application/json")] + [Put("/pet")] + Task Execute([Body] Pet body, CancellationToken cancellationToken = default); + + } + + /// Add a new pet to the store + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IAddPetEndpoint + { + /// Add a new pet to the store + /// Add a new pet to the store + /// Create a new pet in the store + /// The cancellation token to cancel the request. + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Content-Type: application/json")] + [Post("/pet")] + Task Execute([Body] Pet body, CancellationToken cancellationToken = default); + + } + + /// Finds Pets by status + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IFindPetsByStatusEndpoint + { + /// Finds Pets by status + /// Multiple status values can be provided with comma separated strings + /// Status values that need to be considered for filter + /// The cancellation token to cancel the request. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid status value + /// + /// + /// + [Get("/pet/findByStatus")] + Task> Execute([Query] Status? status, CancellationToken cancellationToken = default); + + } + + /// Finds Pets by tags + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IFindPetsByTagsEndpoint + { + /// Finds Pets by tags + /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// Tags to filter by + /// The cancellation token to cancel the request. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid tag value + /// + /// + /// + [Get("/pet/findByTags")] + Task> Execute([Query(CollectionFormat.Multi)] IEnumerable tags, CancellationToken cancellationToken = default); + + } + + /// Find pet by ID + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IGetPetByIdEndpoint + { + /// Find pet by ID + /// Returns a single pet + /// ID of pet to return + /// The cancellation token to cancel the request. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// + [Get("/pet/{petId}")] + Task Execute(long petId, CancellationToken cancellationToken = default); + + } + + /// Updates a pet in the store with form data + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IUpdatePetWithFormEndpoint + { + /// Updates a pet in the store with form data + /// ID of pet that needs to be updated + /// Name of pet that needs to be updated + /// Status of pet that needs to be updated + /// The cancellation token to cancel the request. + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Post("/pet/{petId}")] + Task Execute(long petId, [Query] string name, [Query] string status, CancellationToken cancellationToken = default); + + } + + /// Deletes a pet + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IDeletePetEndpoint + { + /// Deletes a pet + /// api_key parameter + /// Pet id to delete + /// The cancellation token to cancel the request. + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid pet value + /// + /// + /// + [Delete("/pet/{petId}")] + Task Execute(long petId, [Header("api_key")] string api_key, CancellationToken cancellationToken = default); + + } + + /// uploads an image + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IUploadFileEndpoint + { + /// uploads an image + /// ID of pet to update + /// Additional Metadata + /// body parameter + /// The cancellation token to cancel the request. + /// + /// A representing the instance containing the result: + /// + /// + /// Status + /// Description + /// + /// + /// 200 + /// successful operation + /// + /// + /// + [Headers("Content-Type: application/octet-stream")] + [Post("/pet/{petId}/uploadImage")] + Task Execute(long petId, [Query] string additionalMetadata, StreamPart body, CancellationToken cancellationToken = default); + + } + + /// Returns pet inventories by status + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IGetInventoryEndpoint + { + /// Returns pet inventories by status + /// Returns a map of status codes to quantities + /// The cancellation token to cancel the request. + /// successful operation + /// Thrown when the request returns a non-success status code. + [Get("/store/inventory")] + Task> Execute(CancellationToken cancellationToken = default); + + } + + /// Place an order for a pet + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IPlaceOrderEndpoint + { + /// Place an order for a pet + /// Place a new order in the store + /// body parameter + /// The cancellation token to cancel the request. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Content-Type: application/json")] + [Post("/store/order")] + Task Execute([Body] Order body, CancellationToken cancellationToken = default); + + } + + /// Find purchase order by ID + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IGetOrderByIdEndpoint + { + /// Find purchase order by ID + /// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + /// ID of order that needs to be fetched + /// The cancellation token to cancel the request. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Get("/store/order/{orderId}")] + Task Execute(long orderId, CancellationToken cancellationToken = default); + + } + + /// Delete purchase order by ID + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IDeleteOrderEndpoint + { + /// Delete purchase order by ID + /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// ID of the order that needs to be deleted + /// The cancellation token to cancel the request. + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Delete("/store/order/{orderId}")] + Task Execute(long orderId, CancellationToken cancellationToken = default); + + } + + /// Create user + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ICreateUserEndpoint + { + /// Create user + /// This can only be done by the logged in user. + /// Created user object + /// The cancellation token to cancel the request. + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Post("/user")] + Task Execute([Body] User body, CancellationToken cancellationToken = default); + + } + + /// Creates list of users with given input array + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ICreateUsersWithListInputEndpoint + { + /// Creates list of users with given input array + /// Creates list of users with given input array + /// body parameter + /// The cancellation token to cancel the request. + /// Successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Post("/user/createWithList")] + Task Execute([Body] IEnumerable body, CancellationToken cancellationToken = default); + + } + + /// Logs user into the system + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ILoginUserEndpoint + { + /// Logs user into the system + /// The user name for login + /// The password for login in clear text + /// The cancellation token to cancel the request. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username/password supplied + /// + /// + /// + [Get("/user/login")] + Task Execute([Query] string username, [Query] string password, CancellationToken cancellationToken = default); + + } + + /// Logs out current logged in user session + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ILogoutUserEndpoint + { + /// Logs out current logged in user session + /// The cancellation token to cancel the request. + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Get("/user/logout")] + Task Execute(CancellationToken cancellationToken = default); + + } + + /// Get user by user name + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IGetUserByNameEndpoint + { + /// Get user by user name + /// The name that needs to be fetched. Use user1 for testing. + /// The cancellation token to cancel the request. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Get("/user/{username}")] + Task Execute(string username, CancellationToken cancellationToken = default); + + } + + /// Update user + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IUpdateUserEndpoint + { + /// Update user + /// This can only be done by the logged in user. + /// name that need to be deleted + /// Update an existent user in the store + /// The cancellation token to cancel the request. + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Put("/user/{username}")] + Task Execute(string username, [Body] User body, CancellationToken cancellationToken = default); + + } + + /// Delete user + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IDeleteUserEndpoint + { + /// Delete user + /// This can only be done by the logged in user. + /// The name that needs to be deleted + /// The cancellation token to cancel the request. + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Delete("/user/{username}")] + Task Execute(string username, CancellationToken cancellationToken = default); + + } + +} + + + + + +#nullable enable +namespace Refitter.Tests.AdditionalFiles.ByEndpoint +{ + using System; + using Microsoft.Extensions.DependencyInjection; + using Refit; + + /// + /// Extension methods for configuring Refit clients in the service collection. + /// + public static partial class IServiceCollectionExtensions + { + /// + /// Configures the Refit clients for dependency injection. + /// + /// The service collection to configure. + /// The base URL for the API clients. + /// Optional action to configure the HTTP client builder. + /// Optional Refit settings to customize serialization and other behaviors. + /// The configured service collection. + public static IServiceCollection ConfigureRefitClients( + this IServiceCollection services, + Uri baseUrl, + Action? builder = default, + RefitSettings? settings = default) + { + var clientBuilderIUpdatePetEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIUpdatePetEndpoint); + + var clientBuilderIAddPetEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIAddPetEndpoint); + + var clientBuilderIFindPetsByStatusEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIFindPetsByStatusEndpoint); + + var clientBuilderIFindPetsByTagsEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIFindPetsByTagsEndpoint); + + var clientBuilderIGetPetByIdEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIGetPetByIdEndpoint); + + var clientBuilderIUpdatePetWithFormEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIUpdatePetWithFormEndpoint); + + var clientBuilderIDeletePetEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIDeletePetEndpoint); + + var clientBuilderIUploadFileEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIUploadFileEndpoint); + + var clientBuilderIGetInventoryEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIGetInventoryEndpoint); + + var clientBuilderIPlaceOrderEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIPlaceOrderEndpoint); + + var clientBuilderIGetOrderByIdEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIGetOrderByIdEndpoint); + + var clientBuilderIDeleteOrderEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIDeleteOrderEndpoint); + + var clientBuilderICreateUserEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderICreateUserEndpoint); + + var clientBuilderICreateUsersWithListInputEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderICreateUsersWithListInputEndpoint); + + var clientBuilderILoginUserEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderILoginUserEndpoint); + + var clientBuilderILogoutUserEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderILogoutUserEndpoint); + + var clientBuilderIGetUserByNameEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIGetUserByNameEndpoint); + + var clientBuilderIUpdateUserEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIUpdateUserEndpoint); + + var clientBuilderIDeleteUserEndpoint = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = baseUrl) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + builder?.Invoke(clientBuilderIDeleteUserEndpoint); + + return services; + } + } +} \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfacesByTag.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfacesByTag.g.cs new file mode 100644 index 000000000..590f9a485 --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreMultipleInterfacesByTag.g.cs @@ -0,0 +1,388 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +using Refitter.Tests.AdditionalFiles.SingeInterface; + +#nullable enable annotations + +namespace Refitter.Tests.AdditionalFiles.ByTag +{ + /// Everything about your Pets + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IPetApi + { + /// Update an existing pet + /// Update an existing pet by Id + /// Update an existent pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// 405 + /// Validation exception + /// + /// + /// + [Headers("Content-Type: application/json")] + [Put("/pet")] + Task UpdatePet([Body] Pet body); + + /// Add a new pet to the store + /// Add a new pet to the store + /// Create a new pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Content-Type: application/json")] + [Post("/pet")] + Task AddPet([Body] Pet body); + + /// Finds Pets by status + /// Multiple status values can be provided with comma separated strings + /// Status values that need to be considered for filter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid status value + /// + /// + /// + [Get("/pet/findByStatus")] + Task> FindPetsByStatus([Query] Status? status); + + /// Finds Pets by tags + /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// Tags to filter by + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid tag value + /// + /// + /// + [Get("/pet/findByTags")] + Task> FindPetsByTags([Query(CollectionFormat.Multi)] IEnumerable tags); + + /// Find pet by ID + /// Returns a single pet + /// ID of pet to return + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// + [Get("/pet/{petId}")] + Task GetPetById(long petId); + + /// Updates a pet in the store with form data + /// ID of pet that needs to be updated + /// Name of pet that needs to be updated + /// Status of pet that needs to be updated + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Post("/pet/{petId}")] + Task UpdatePetWithForm(long petId, [Query] string name, [Query] string status); + + /// Deletes a pet + /// api_key parameter + /// Pet id to delete + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid pet value + /// + /// + /// + [Delete("/pet/{petId}")] + Task DeletePet(long petId, [Header("api_key")] string api_key); + + /// uploads an image + /// ID of pet to update + /// Additional Metadata + /// body parameter + /// + /// A representing the instance containing the result: + /// + /// + /// Status + /// Description + /// + /// + /// 200 + /// successful operation + /// + /// + /// + [Headers("Content-Type: application/octet-stream")] + [Post("/pet/{petId}/uploadImage")] + Task UploadFile(long petId, [Query] string additionalMetadata, StreamPart body); + + } + + /// Operations about user + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IStoreApi + { + /// Returns pet inventories by status + /// Returns a map of status codes to quantities + /// successful operation + /// Thrown when the request returns a non-success status code. + [Get("/store/inventory")] + Task> GetInventory(); + + /// Place an order for a pet + /// Place a new order in the store + /// body parameter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Content-Type: application/json")] + [Post("/store/order")] + Task PlaceOrder([Body] Order body); + + /// Find purchase order by ID + /// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + /// ID of order that needs to be fetched + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Get("/store/order/{orderId}")] + Task GetOrderById(long orderId); + + /// Delete purchase order by ID + /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// ID of the order that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Delete("/store/order/{orderId}")] + Task DeleteOrder(long orderId); + + } + + /// Access to Petstore orders + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IUserApi + { + /// Create user + /// This can only be done by the logged in user. + /// Created user object + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Post("/user")] + Task CreateUser([Body] User body); + + /// Creates list of users with given input array + /// Creates list of users with given input array + /// body parameter + /// Successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Post("/user/createWithList")] + Task CreateUsersWithListInput([Body] IEnumerable body); + + /// Logs user into the system + /// The user name for login + /// The password for login in clear text + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username/password supplied + /// + /// + /// + [Get("/user/login")] + Task LoginUser([Query] string username, [Query] string password); + + /// Logs out current logged in user session + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Get("/user/logout")] + Task LogoutUser(); + + /// Get user by user name + /// The name that needs to be fetched. Use user1 for testing. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Get("/user/{username}")] + Task GetUserByName(string username); + + /// Update user + /// This can only be done by the logged in user. + /// name that need to be deleted + /// Update an existent user in the store + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Put("/user/{username}")] + Task UpdateUser(string username, [Body] User body); + + /// Delete user + /// This can only be done by the logged in user. + /// The name that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Delete("/user/{username}")] + Task DeleteUser(string username); + + } + +} \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreOptionalParameters.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreOptionalParameters.g.cs new file mode 100644 index 000000000..3f50d209b --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreOptionalParameters.g.cs @@ -0,0 +1,737 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#nullable enable annotations + +namespace Refitter.Tests.AdditionalFiles.OptionalParameters +{ + /// Swagger Petstore - OpenAPI 3.0 + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ISwaggerPetstoreWithOptionalParameters + { + /// Update an existing pet + /// Update an existing pet by Id + /// Update an existent pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// 405 + /// Validation exception + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Put("/pet")] + Task UpdatePet([Body] Pet body); + + /// Add a new pet to the store + /// Add a new pet to the store + /// Create a new pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/pet")] + Task AddPet([Body] Pet body); + + /// Finds Pets by status + /// Multiple status values can be provided with comma separated strings + /// Status values that need to be considered for filter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid status value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByStatus")] + Task> FindPetsByStatus([Query] Status? status = default); + + /// Finds Pets by tags + /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// Tags to filter by + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid tag value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByTags")] + Task> FindPetsByTags([Query(CollectionFormat.Multi)] IEnumerable? tags = default); + + /// Find pet by ID + /// Returns a single pet + /// ID of pet to return + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// + [Headers("Accept: application/xml, application/json")] + [Get("/pet/{petId}")] + Task GetPetById(long petId); + + /// Updates a pet in the store with form data + /// ID of pet that needs to be updated + /// Name of pet that needs to be updated + /// Status of pet that needs to be updated + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Post("/pet/{petId}")] + Task UpdatePetWithForm(long petId, [Query] string? name = default, [Query] string? status = default); + + /// Deletes a pet + /// api_key parameter + /// Pet id to delete + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid pet value + /// + /// + /// + [Delete("/pet/{petId}")] + Task DeletePet(long petId, [Header("api_key")] string? api_key = default); + + /// uploads an image + /// ID of pet to update + /// Additional Metadata + /// body parameter + /// + /// A representing the instance containing the result: + /// + /// + /// Status + /// Description + /// + /// + /// 200 + /// successful operation + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/octet-stream")] + [Post("/pet/{petId}/uploadImage")] + Task UploadFile(long petId, StreamPart body, [Query] string? additionalMetadata = default); + + /// Returns pet inventories by status + /// Returns a map of status codes to quantities + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json")] + [Get("/store/inventory")] + Task> GetInventory(); + + /// Place an order for a pet + /// Place a new order in the store + /// body parameter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/json")] + [Post("/store/order")] + Task PlaceOrder([Body] Order? body = default); + + /// Find purchase order by ID + /// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + /// ID of order that needs to be fetched + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/store/order/{orderId}")] + Task GetOrderById(long orderId); + + /// Delete purchase order by ID + /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// ID of the order that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Delete("/store/order/{orderId}")] + Task DeleteOrder(long orderId); + + /// Create user + /// This can only be done by the logged in user. + /// Created user object + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json, application/xml", "Content-Type: application/json")] + [Post("/user")] + Task CreateUser([Body] User? body = default); + + /// Creates list of users with given input array + /// Creates list of users with given input array + /// body parameter + /// Successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/user/createWithList")] + Task CreateUsersWithListInput([Body] IEnumerable? body = default); + + /// Logs user into the system + /// The user name for login + /// The password for login in clear text + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username/password supplied + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/login")] + Task LoginUser([Query] string? username = default, [Query] string? password = default); + + /// Logs out current logged in user session + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Get("/user/logout")] + Task LogoutUser(); + + /// Get user by user name + /// The name that needs to be fetched. Use user1 for testing. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/{username}")] + Task GetUserByName(string username); + + /// Update user + /// This can only be done by the logged in user. + /// name that need to be deleted + /// Update an existent user in the store + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Put("/user/{username}")] + Task UpdateUser(string username, [Body] User? body = default); + + /// Delete user + /// This can only be done by the logged in user. + /// The name that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Delete("/user/{username}")] + Task DeleteUser(string username); + + } + + +} + +//---------------------- +// +// Generated using the NSwag toolchain v14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." +#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." +#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' +#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" +#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... +#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." +#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" +#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" +#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" +#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" +#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." + +namespace Refitter.Tests.AdditionalFiles.OptionalParameters +{ + using System = global::System; + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Order + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("petId")] + public long PetId { get; set; } + + [JsonPropertyName("quantity")] + public int Quantity { get; set; } + + [JsonPropertyName("shipDate")] + public System.DateTimeOffset ShipDate { get; set; } + + /// + /// Order Status + /// + [JsonPropertyName("status")] +public OrderStatus Status { get; set; } + + [JsonPropertyName("complete")] + public bool Complete { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Customer + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("address")] + public ICollection
Address { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Address + { + + [JsonPropertyName("street")] + public string Street { get; set; } + + [JsonPropertyName("city")] + public string City { get; set; } + + [JsonPropertyName("state")] + public string State { get; set; } + + [JsonPropertyName("zip")] + public string Zip { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Category + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class User + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("firstName")] + public string FirstName { get; set; } + + [JsonPropertyName("lastName")] + public string LastName { get; set; } + + [JsonPropertyName("email")] + public string Email { get; set; } + + [JsonPropertyName("password")] + public string Password { get; set; } + + [JsonPropertyName("phone")] + public string Phone { get; set; } + + /// + /// User Status + /// + [JsonPropertyName("userStatus")] + public int UserStatus { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Tag + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Pet + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + public string Name { get; set; } + + [JsonPropertyName("category")] + public Category Category { get; set; } + + [JsonPropertyName("photoUrls")] + [System.ComponentModel.DataAnnotations.Required] + public ICollection PhotoUrls { get; set; } = new System.Collections.ObjectModel.Collection(); + + [JsonPropertyName("tags")] + public ICollection Tags { get; set; } + + /// + /// pet status in the store + /// + [JsonPropertyName("status")] +public PetStatus Status { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ApiResponse + { + + [JsonPropertyName("code")] + public int Code { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("message")] + public string Message { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum Status + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum OrderStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"placed")] + Placed = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"approved")] + Approved = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"delivered")] + Delivered = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum PetStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class FileParameter + { + public FileParameter(System.IO.Stream data) + : this (data, null, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName) + : this (data, fileName, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName, string contentType) + { + Data = data; + FileName = fileName; + ContentType = contentType; + } + + public System.IO.Stream Data { get; private set; } + + public string FileName { get; private set; } + + public string ContentType { get; private set; } + } + + +} + +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 +#pragma warning restore 649 +#pragma warning restore 1573 +#pragma warning restore 1591 +#pragma warning restore 8073 +#pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 +#pragma warning restore 8603 +#pragma warning restore 8604 +#pragma warning restore 8625 +#pragma warning restore 8765 \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithHttpResilience.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithHttpResilience.g.cs new file mode 100644 index 000000000..9251c354f --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithHttpResilience.g.cs @@ -0,0 +1,786 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#nullable enable annotations + +namespace Refitter.Tests.AdditionalFiles.SingeInterfaceWithHttpResilience +{ + /// Swagger Petstore - OpenAPI 3.0 + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ISwaggerPetstoreInterfaceWithHttpResilience + { + /// Update an existing pet + /// Update an existing pet by Id + /// Update an existent pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// 405 + /// Validation exception + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Put("/pet")] + Task UpdatePet([Body] Pet body); + + /// Add a new pet to the store + /// Add a new pet to the store + /// Create a new pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/pet")] + Task AddPet([Body] Pet body); + + /// Finds Pets by status + /// Multiple status values can be provided with comma separated strings + /// Status values that need to be considered for filter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid status value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByStatus")] + Task> FindPetsByStatus([Query] Status? status); + + /// Finds Pets by tags + /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// Tags to filter by + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid tag value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByTags")] + Task> FindPetsByTags([Query(CollectionFormat.Multi)] IEnumerable tags); + + /// Find pet by ID + /// Returns a single pet + /// ID of pet to return + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// + [Headers("Accept: application/xml, application/json")] + [Get("/pet/{petId}")] + Task GetPetById(long petId); + + /// Updates a pet in the store with form data + /// ID of pet that needs to be updated + /// Name of pet that needs to be updated + /// Status of pet that needs to be updated + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Post("/pet/{petId}")] + Task UpdatePetWithForm(long petId, [Query] string name, [Query] string status); + + /// Deletes a pet + /// api_key parameter + /// Pet id to delete + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid pet value + /// + /// + /// + [Delete("/pet/{petId}")] + Task DeletePet(long petId, [Header("api_key")] string api_key); + + /// uploads an image + /// ID of pet to update + /// Additional Metadata + /// body parameter + /// + /// A representing the instance containing the result: + /// + /// + /// Status + /// Description + /// + /// + /// 200 + /// successful operation + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/octet-stream")] + [Post("/pet/{petId}/uploadImage")] + Task UploadFile(long petId, [Query] string additionalMetadata, StreamPart body); + + /// Returns pet inventories by status + /// Returns a map of status codes to quantities + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json")] + [Get("/store/inventory")] + Task> GetInventory(); + + /// Place an order for a pet + /// Place a new order in the store + /// body parameter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/json")] + [Post("/store/order")] + Task PlaceOrder([Body] Order body); + + /// Find purchase order by ID + /// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + /// ID of order that needs to be fetched + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/store/order/{orderId}")] + Task GetOrderById(long orderId); + + /// Delete purchase order by ID + /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// ID of the order that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Delete("/store/order/{orderId}")] + Task DeleteOrder(long orderId); + + /// Create user + /// This can only be done by the logged in user. + /// Created user object + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json, application/xml", "Content-Type: application/json")] + [Post("/user")] + Task CreateUser([Body] User body); + + /// Creates list of users with given input array + /// Creates list of users with given input array + /// body parameter + /// Successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/user/createWithList")] + Task CreateUsersWithListInput([Body] IEnumerable body); + + /// Logs user into the system + /// The user name for login + /// The password for login in clear text + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username/password supplied + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/login")] + Task LoginUser([Query] string username, [Query] string password); + + /// Logs out current logged in user session + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Get("/user/logout")] + Task LogoutUser(); + + /// Get user by user name + /// The name that needs to be fetched. Use user1 for testing. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/{username}")] + Task GetUserByName(string username); + + /// Update user + /// This can only be done by the logged in user. + /// name that need to be deleted + /// Update an existent user in the store + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Put("/user/{username}")] + Task UpdateUser(string username, [Body] User body); + + /// Delete user + /// This can only be done by the logged in user. + /// The name that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Delete("/user/{username}")] + Task DeleteUser(string username); + + } + + +} + +//---------------------- +// +// Generated using the NSwag toolchain v14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." +#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." +#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' +#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" +#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... +#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." +#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" +#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" +#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" +#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" +#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." + +namespace Refitter.Tests.AdditionalFiles.SingeInterfaceWithHttpResilience +{ + using System = global::System; + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Order + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("petId")] + public long PetId { get; set; } + + [JsonPropertyName("quantity")] + public int Quantity { get; set; } + + [JsonPropertyName("shipDate")] + public System.DateTimeOffset ShipDate { get; set; } + + /// + /// Order Status + /// + [JsonPropertyName("status")] +public OrderStatus Status { get; set; } + + [JsonPropertyName("complete")] + public bool Complete { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Customer + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("address")] + public ICollection
Address { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Address + { + + [JsonPropertyName("street")] + public string Street { get; set; } + + [JsonPropertyName("city")] + public string City { get; set; } + + [JsonPropertyName("state")] + public string State { get; set; } + + [JsonPropertyName("zip")] + public string Zip { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Category + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class User + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("firstName")] + public string FirstName { get; set; } + + [JsonPropertyName("lastName")] + public string LastName { get; set; } + + [JsonPropertyName("email")] + public string Email { get; set; } + + [JsonPropertyName("password")] + public string Password { get; set; } + + [JsonPropertyName("phone")] + public string Phone { get; set; } + + /// + /// User Status + /// + [JsonPropertyName("userStatus")] + public int UserStatus { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Tag + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Pet + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + public string Name { get; set; } + + [JsonPropertyName("category")] + public Category Category { get; set; } + + [JsonPropertyName("photoUrls")] + [System.ComponentModel.DataAnnotations.Required] + public ICollection PhotoUrls { get; set; } = new System.Collections.ObjectModel.Collection(); + + [JsonPropertyName("tags")] + public ICollection Tags { get; set; } + + /// + /// pet status in the store + /// + [JsonPropertyName("status")] +public PetStatus Status { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ApiResponse + { + + [JsonPropertyName("code")] + public int Code { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("message")] + public string Message { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum Status + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum OrderStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"placed")] + Placed = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"approved")] + Approved = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"delivered")] + Delivered = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum PetStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class FileParameter + { + public FileParameter(System.IO.Stream data) + : this (data, null, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName) + : this (data, fileName, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName, string contentType) + { + Data = data; + FileName = fileName; + ContentType = contentType; + } + + public System.IO.Stream Data { get; private set; } + + public string FileName { get; private set; } + + public string ContentType { get; private set; } + } + + +} + +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 +#pragma warning restore 649 +#pragma warning restore 1573 +#pragma warning restore 1591 +#pragma warning restore 8073 +#pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 +#pragma warning restore 8603 +#pragma warning restore 8604 +#pragma warning restore 8625 +#pragma warning restore 8765 + + + +#nullable enable +namespace Refitter.Tests.AdditionalFiles.SingeInterfaceWithHttpResilience +{ + using System; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Http.Resilience; + using Refit; + + /// + /// Extension methods for configuring Refit clients in the service collection. + /// + public static partial class IServiceCollectionExtensions + { + /// + /// Configures the Refit clients for dependency injection. + /// + /// The service collection to configure. +/// Optional action to configure the HTTP client builder. + /// Optional Refit settings to customize serialization and other behaviors. + /// The configured service collection. + public static IServiceCollection ConfigureRefitClients( + this IServiceCollection services, + Action? builder = default, + RefitSettings? settings = default) + { + var clientBuilderISwaggerPetstoreInterfaceWithHttpResilience = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://petstore3.swagger.io/api/v3")); + + clientBuilderISwaggerPetstoreInterfaceWithHttpResilience + .AddStandardResilienceHandler(config => + { + config.Retry = new HttpRetryStrategyOptions + { + UseJitter = true, + MaxRetryAttempts = 3, + Delay = TimeSpan.FromSeconds(0.5) + }; + }); + + builder?.Invoke(clientBuilderISwaggerPetstoreInterfaceWithHttpResilience); + + return services; + } + } +} \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithPolly.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithPolly.g.cs new file mode 100644 index 000000000..f9a7113ca --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/SwaggerPetstoreSingleInterfaceWithPolly.g.cs @@ -0,0 +1,488 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#nullable enable annotations + +namespace Refitter.Tests.AdditionalFiles.SingeInterface +{ + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface ISwaggerPetstoreInterface + { + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Put("/pet")] + Task UpdatePet([Body] Pet body); + + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/pet")] + Task AddPet([Body] Pet body); + + [Headers("Accept: application/json")] + [Get("/pet/findByStatus")] + Task> FindPetsByStatus([Query] Status? status); + + [Headers("Accept: application/json")] + [Get("/pet/findByTags")] + Task> FindPetsByTags([Query(CollectionFormat.Multi)] IEnumerable tags); + + [Headers("Accept: application/xml, application/json")] + [Get("/pet/{petId}")] + Task GetPetById(long petId); + + [Post("/pet/{petId}")] + Task UpdatePetWithForm(long petId, [Query] string name, [Query] string status); + + [Delete("/pet/{petId}")] + Task DeletePet(long petId, [Header("api_key")] string api_key); + + [Headers("Accept: application/json", "Content-Type: application/octet-stream")] + [Post("/pet/{petId}/uploadImage")] + Task UploadFile(long petId, [Query] string additionalMetadata, StreamPart body); + + [Headers("Accept: application/json")] + [Get("/store/inventory")] + Task> GetInventory(); + + [Headers("Accept: application/json", "Content-Type: application/json")] + [Post("/store/order")] + Task PlaceOrder([Body] Order body); + + [Headers("Accept: application/json")] + [Get("/store/order/{orderId}")] + Task GetOrderById(long orderId); + + [Delete("/store/order/{orderId}")] + Task DeleteOrder(long orderId); + + [Headers("Accept: application/json, application/xml", "Content-Type: application/json")] + [Post("/user")] + Task CreateUser([Body] User body); + + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/user/createWithList")] + Task CreateUsersWithListInput([Body] IEnumerable body); + + [Headers("Accept: application/json")] + [Get("/user/login")] + Task LoginUser([Query] string username, [Query] string password); + + [Get("/user/logout")] + Task LogoutUser(); + + [Headers("Accept: application/json")] + [Get("/user/{username}")] + Task GetUserByName(string username); + + [Headers("Content-Type: application/json")] + [Put("/user/{username}")] + Task UpdateUser(string username, [Body] User body); + + [Delete("/user/{username}")] + Task DeleteUser(string username); + + } + + +} + +//---------------------- +// +// Generated using the NSwag toolchain v14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." +#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." +#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' +#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" +#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... +#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." +#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" +#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" +#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" +#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" +#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." + +namespace Refitter.Tests.AdditionalFiles.SingeInterface +{ + using System = global::System; + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Order + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("petId")] + public long PetId { get; set; } + + [JsonPropertyName("quantity")] + public int Quantity { get; set; } + + [JsonPropertyName("shipDate")] + public System.DateTimeOffset ShipDate { get; set; } + + /// + /// Order Status + /// + [JsonPropertyName("status")] +public OrderStatus Status { get; set; } + + [JsonPropertyName("complete")] + public bool Complete { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Customer + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("address")] + public ICollection
Address { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Address + { + + [JsonPropertyName("street")] + public string Street { get; set; } + + [JsonPropertyName("city")] + public string City { get; set; } + + [JsonPropertyName("state")] + public string State { get; set; } + + [JsonPropertyName("zip")] + public string Zip { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Category + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class User + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("username")] + public string Username { get; set; } + + [JsonPropertyName("firstName")] + public string FirstName { get; set; } + + [JsonPropertyName("lastName")] + public string LastName { get; set; } + + [JsonPropertyName("email")] + public string Email { get; set; } + + [JsonPropertyName("password")] + public string Password { get; set; } + + [JsonPropertyName("phone")] + public string Phone { get; set; } + + /// + /// User Status + /// + [JsonPropertyName("userStatus")] + public int UserStatus { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Tag + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Pet + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("name")] + [System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)] + public string Name { get; set; } + + [JsonPropertyName("category")] + public Category Category { get; set; } + + [JsonPropertyName("photoUrls")] + [System.ComponentModel.DataAnnotations.Required] + public ICollection PhotoUrls { get; set; } = new System.Collections.ObjectModel.Collection(); + + [JsonPropertyName("tags")] + public ICollection Tags { get; set; } + + /// + /// pet status in the store + /// + [JsonPropertyName("status")] +public PetStatus Status { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ApiResponse + { + + [JsonPropertyName("code")] + public int Code { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("message")] + public string Message { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum Status + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum OrderStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"placed")] + Placed = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"approved")] + Approved = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"delivered")] + Delivered = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum PetStatus + { + + [System.Runtime.Serialization.EnumMember(Value = @"available")] + Available = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"pending")] + Pending = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"sold")] + Sold = 2, + + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class FileParameter + { + public FileParameter(System.IO.Stream data) + : this (data, null, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName) + : this (data, fileName, null) + { + } + + public FileParameter(System.IO.Stream data, string fileName, string contentType) + { + Data = data; + FileName = fileName; + ContentType = contentType; + } + + public System.IO.Stream Data { get; private set; } + + public string FileName { get; private set; } + + public string ContentType { get; private set; } + } + + +} + +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 +#pragma warning restore 649 +#pragma warning restore 1573 +#pragma warning restore 1591 +#pragma warning restore 8073 +#pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 +#pragma warning restore 8603 +#pragma warning restore 8604 +#pragma warning restore 8625 +#pragma warning restore 8765 + + + +#nullable enable +namespace Refitter.Tests.AdditionalFiles.SingeInterface +{ + using System; + using Microsoft.Extensions.DependencyInjection; + using Polly; + using Polly.Contrib.WaitAndRetry; + using Polly.Extensions.Http; + using Refit; + + public static partial class IServiceCollectionExtensions + { + public static IServiceCollection ConfigureRefitClients( + this IServiceCollection services, + Action? builder = default, + RefitSettings? settings = default) + { + var clientBuilderISwaggerPetstoreInterface = services + .AddRefitClient(settings) + .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://petstore3.swagger.io/api/v3")) + .AddHttpMessageHandler() + .AddHttpMessageHandler(); + + clientBuilderISwaggerPetstoreInterface + .AddPolicyHandler( + HttpPolicyExtensions + .HandleTransientHttpError() + .WaitAndRetryAsync( + Backoff.DecorrelatedJitterBackoffV2( + TimeSpan.FromSeconds(0.5), + 3))); + + builder?.Invoke(clientBuilderISwaggerPetstoreInterface); + + return services; + } + } +} \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UseJsonInheritanceConverter.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UseJsonInheritanceConverter.g.cs new file mode 100644 index 000000000..e0fbdcfc5 --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UseJsonInheritanceConverter.g.cs @@ -0,0 +1,391 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#nullable enable annotations + +namespace Refitter.Tests.UseJsonInheritanceConverter +{ + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IApiClient + { + /// Some Token + /// body parameter + /// Created + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Bad Request + /// + /// + /// 500 + /// Server Error + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/json")] + [Post("/v1/Warehouses")] + Task> CreateWarehouse([Query] string token, [Body] Warehouse body); + + } + + +} + +//---------------------- +// +// Generated using the NSwag toolchain v14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." +#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." +#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' +#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" +#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... +#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." +#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" +#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" +#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" +#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" +#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." + +namespace Refitter.Tests.UseJsonInheritanceConverter +{ + using System = global::System; + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Metadata + { + + [JsonPropertyName("createdAt")] + public System.DateTimeOffset CreatedAt { get; set; } + + [JsonPropertyName("createdBy")] + public string CreatedBy { get; set; } + + [JsonPropertyName("lastModifiedAt")] + public System.DateTimeOffset LastModifiedAt { get; set; } + + [JsonPropertyName("lastModifiedBy")] + public string LastModifiedBy { get; set; } + + } + + [JsonInheritanceConverter(typeof(SomeComponent), "$type")] + [JsonInheritanceAttribute("Warehouse", typeof(Warehouse))] + [JsonInheritanceAttribute("WarehouseResponse", typeof(WarehouseResponse))] + [JsonInheritanceAttribute("LoadingAddress", typeof(LoadingAddress))] + [JsonInheritanceAttribute("UserComponent", typeof(UserComponent))] + [JsonInheritanceAttribute("UserComponent2", typeof(UserComponent2))] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class SomeComponent : Component + { + + [JsonPropertyName("typeId")] + public long TypeId { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum SomeComponentState + { + + [System.Runtime.Serialization.EnumMember(Value = @"Active")] + Active = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"Inactive")] + Inactive = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"Blocked")] + Blocked = 2, + + [System.Runtime.Serialization.EnumMember(Value = @"Deleted")] + Deleted = 3, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class SomeComponentType : Component + { + + [JsonPropertyName("state")] +public SomeComponentState State { get; set; } + + [JsonPropertyName("isBaseRole")] + public bool IsBaseRole { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("numberingId")] + public string NumberingId { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Component + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("metadata")] + public Metadata Metadata { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class LoadingAddress : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Warehouse : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class WarehouseResponse : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class UserComponent : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class UserComponent2 : UserComponent + { + + [JsonPropertyName("info2")] + public string Info2 { get; set; } + + } + + [JsonInheritanceConverter(typeof(ProblemDetails), "$type")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ProblemDetails + { + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("title")] + public string Title { get; set; } + + [JsonPropertyName("status")] + public int? Status { get; set; } + + [JsonPropertyName("detail")] + public string Detail { get; set; } + + [JsonPropertyName("instance")] + public string Instance { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [System.AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Interface, AllowMultiple = true)] + internal class JsonInheritanceAttribute : System.Attribute + { + public JsonInheritanceAttribute(string key, System.Type type) + { + Key = key; + Type = type; + } + + public string Key { get; } + + public System.Type Type { get; } + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + internal class JsonInheritanceConverterAttribute : JsonConverterAttribute + { + public string DiscriminatorName { get; } + + public JsonInheritanceConverterAttribute(System.Type baseType, string discriminatorName = "discriminator") + : base(typeof(JsonInheritanceConverter<>).MakeGenericType(baseType)) + { + DiscriminatorName = discriminatorName; + } + } + + public class JsonInheritanceConverter : JsonConverter + { + private readonly string _discriminatorName; + + public JsonInheritanceConverter() + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(typeof(TBase)); + _discriminatorName = attribute?.DiscriminatorName ?? "discriminator"; + } + + public JsonInheritanceConverter(string discriminatorName) + { + _discriminatorName = discriminatorName; + } + + public string DiscriminatorName { get { return _discriminatorName; } } + + public override TBase Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) + { + var document = System.Text.Json.JsonDocument.ParseValue(ref reader); + var hasDiscriminator = document.RootElement.TryGetProperty(_discriminatorName, out var discriminator); + var subtype = GetDiscriminatorType(document.RootElement, typeToConvert, hasDiscriminator ? discriminator.GetString() : null); + + var bufferWriter = new System.IO.MemoryStream(); + using (var writer = new System.Text.Json.Utf8JsonWriter(bufferWriter)) + { + document.RootElement.WriteTo(writer); + } + + return (TBase)System.Text.Json.JsonSerializer.Deserialize(bufferWriter.ToArray(), subtype, options); + } + + public override void Write(System.Text.Json.Utf8JsonWriter writer, TBase value, System.Text.Json.JsonSerializerOptions options) + { + if (value != null) + { + writer.WriteStartObject(); + writer.WriteString(_discriminatorName, GetDiscriminatorValue(value.GetType())); + + var bytes = System.Text.Json.JsonSerializer.SerializeToUtf8Bytes((object)value, options); + var document = System.Text.Json.JsonDocument.Parse(bytes); + foreach (var property in document.RootElement.EnumerateObject()) + { + property.WriteTo(writer); + } + + writer.WriteEndObject(); + } + else + { + writer.WriteNullValue(); + } + } + + public string GetDiscriminatorValue(System.Type type) + { + var jsonInheritanceAttributeDiscriminator = GetSubtypeDiscriminator(type); + if (jsonInheritanceAttributeDiscriminator != null) + { + return jsonInheritanceAttributeDiscriminator; + } + + return type.Name; + } + + protected System.Type GetDiscriminatorType(System.Text.Json.JsonElement jObject, System.Type objectType, string discriminatorValue) + { + if (discriminatorValue != null) + { + var jsonInheritanceAttributeSubtype = GetObjectSubtype(objectType, discriminatorValue); + if (jsonInheritanceAttributeSubtype != null) + { + return jsonInheritanceAttributeSubtype; + } + + if (objectType.Name == discriminatorValue) + { + return objectType; + } + + var typeName = objectType.Namespace + "." + discriminatorValue; + var subtype = System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType).Assembly.GetType(typeName); + if (subtype != null) + { + return subtype; + } + } + + throw new System.InvalidOperationException("Could not find subtype of '" + objectType.Name + "' with discriminator '" + discriminatorValue + "'."); + } + + private System.Type GetObjectSubtype(System.Type baseType, string discriminatorValue) + { + foreach (var attribute in System.Reflection.CustomAttributeExtensions.GetCustomAttributes(System.Reflection.IntrospectionExtensions.GetTypeInfo(baseType), true)) + { + if (attribute.Key == discriminatorValue) + return attribute.Type; + } + + return null; + } + + private string GetSubtypeDiscriminator(System.Type objectType) + { + foreach (var attribute in System.Reflection.CustomAttributeExtensions.GetCustomAttributes(System.Reflection.IntrospectionExtensions.GetTypeInfo(objectType), true)) + { + if (attribute.Type == objectType) + return attribute.Key; + } + + return null; + } + } + + +} + +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 +#pragma warning restore 649 +#pragma warning restore 1573 +#pragma warning restore 1591 +#pragma warning restore 8073 +#pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 +#pragma warning restore 8603 +#pragma warning restore 8604 +#pragma warning restore 8625 +#pragma warning restore 8765 \ No newline at end of file diff --git a/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UsePolymorphicSerialization.g.cs b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UsePolymorphicSerialization.g.cs new file mode 100644 index 000000000..f35f3df2f --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/AdditionalFiles/Generated/UsePolymorphicSerialization.g.cs @@ -0,0 +1,250 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +#nullable enable annotations + +namespace Refitter.Tests.UsePolymorphicSerialization +{ + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IApiClient + { + /// Some Token + /// body parameter + /// Created + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Bad Request + /// + /// + /// 500 + /// Server Error + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/json")] + [Post("/v1/Warehouses")] + Task> CreateWarehouse([Query] string token, [Body] Warehouse body); + + } + + +} + +//---------------------- +// +// Generated using the NSwag toolchain v14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// +//---------------------- + +#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended." +#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." +#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' +#pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" +#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... +#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." +#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" +#pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" +#pragma warning disable 8603 // Disable "CS8603 Possible null reference return" +#pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" +#pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." + +namespace Refitter.Tests.UsePolymorphicSerialization +{ + using System = global::System; + + + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Metadata + { + + [JsonPropertyName("createdAt")] + public System.DateTimeOffset CreatedAt { get; set; } + + [JsonPropertyName("createdBy")] + public string CreatedBy { get; set; } + + [JsonPropertyName("lastModifiedAt")] + public System.DateTimeOffset LastModifiedAt { get; set; } + + [JsonPropertyName("lastModifiedBy")] + public string LastModifiedBy { get; set; } + + } + + [JsonPolymorphic(TypeDiscriminatorPropertyName = "$type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType, IgnoreUnrecognizedTypeDiscriminators = true)] + [JsonDerivedType(typeof(Warehouse), typeDiscriminator: "Warehouse")] + [JsonDerivedType(typeof(WarehouseResponse), typeDiscriminator: "WarehouseResponse")] + [JsonDerivedType(typeof(LoadingAddress), typeDiscriminator: "LoadingAddress")] + [JsonDerivedType(typeof(UserComponent), typeDiscriminator: "UserComponent")] + [JsonDerivedType(typeof(UserComponent2), typeDiscriminator: "UserComponent2")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class SomeComponent : Component + { + + [JsonPropertyName("typeId")] + public long TypeId { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum SomeComponentState + { + + [System.Runtime.Serialization.EnumMember(Value = @"Active")] + Active = 0, + + [System.Runtime.Serialization.EnumMember(Value = @"Inactive")] + Inactive = 1, + + [System.Runtime.Serialization.EnumMember(Value = @"Blocked")] + Blocked = 2, + + [System.Runtime.Serialization.EnumMember(Value = @"Deleted")] + Deleted = 3, + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class SomeComponentType : Component + { + + [JsonPropertyName("state")] +public SomeComponentState State { get; set; } + + [JsonPropertyName("isBaseRole")] + public bool IsBaseRole { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("numberingId")] + public string NumberingId { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Component + { + + [JsonPropertyName("id")] + public long Id { get; set; } + + [JsonPropertyName("metadata")] + public Metadata Metadata { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class LoadingAddress : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class Warehouse : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class WarehouseResponse : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class UserComponent : SomeComponent + { + + [JsonPropertyName("info")] + public string Info { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class UserComponent2 : UserComponent + { + + [JsonPropertyName("info2")] + public string Info2 { get; set; } + + } + + [JsonPolymorphic(TypeDiscriminatorPropertyName = "$type", UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType, IgnoreUnrecognizedTypeDiscriminators = true)] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.7.1.0 (NJsonSchema v11.6.1.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ProblemDetails + { + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("title")] + public string Title { get; set; } + + [JsonPropertyName("status")] + public int? Status { get; set; } + + [JsonPropertyName("detail")] + public string Detail { get; set; } + + [JsonPropertyName("instance")] + public string Instance { get; set; } + + private IDictionary _additionalProperties; + + [JsonExtensionData] + public IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new Dictionary()); } + set { _additionalProperties = value; } + } + + } + + +} + +#pragma warning restore 108 +#pragma warning restore 114 +#pragma warning restore 472 +#pragma warning restore 612 +#pragma warning restore 649 +#pragma warning restore 1573 +#pragma warning restore 1591 +#pragma warning restore 8073 +#pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 +#pragma warning restore 8603 +#pragma warning restore 8604 +#pragma warning restore 8625 +#pragma warning restore 8765 \ No newline at end of file From d401b1d30c5c6b10bdb60cf2ee51da1053686f3d Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:01:21 +0200 Subject: [PATCH 06/11] chore: use local source generator in smoke test projects --- test/SourceGenerator/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SourceGenerator/Directory.Build.props b/test/SourceGenerator/Directory.Build.props index 84fc47291..9b98f51ef 100644 --- a/test/SourceGenerator/Directory.Build.props +++ b/test/SourceGenerator/Directory.Build.props @@ -12,7 +12,7 @@ - + From 96db15a0e34225a062b2038541706b861c04204d Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:01:35 +0200 Subject: [PATCH 07/11] fix: correct relative path to local source generator in smoke tests --- test/SourceGenerator/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SourceGenerator/Directory.Build.props b/test/SourceGenerator/Directory.Build.props index 9b98f51ef..7a506eaf1 100644 --- a/test/SourceGenerator/Directory.Build.props +++ b/test/SourceGenerator/Directory.Build.props @@ -12,7 +12,7 @@ - + From 5e50fceb9a11a7a582cc2e8edad50415401088c3 Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:02:26 +0200 Subject: [PATCH 08/11] fix: remove explicit Compile include to avoid NETSDK1022 duplicate items --- .../Refitter.SourceGenerator.Tests.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj b/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj index 5a84704f2..b8262ae9b 100644 --- a/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj +++ b/src/Refitter.SourceGenerator.Tests/Refitter.SourceGenerator.Tests.csproj @@ -54,7 +54,6 @@ - From 7e1dc96c8353e8f0422d2b0574a77901069f80bb Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:02:37 +0200 Subject: [PATCH 09/11] chore: commit generated files for custom output folder test --- .../CustomGenerated/CustomGenerated.cs | 384 ++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 src/Refitter.SourceGenerator.Tests/CustomGenerated/CustomGenerated.cs diff --git a/src/Refitter.SourceGenerator.Tests/CustomGenerated/CustomGenerated.cs b/src/Refitter.SourceGenerator.Tests/CustomGenerated/CustomGenerated.cs new file mode 100644 index 000000000..6190d311e --- /dev/null +++ b/src/Refitter.SourceGenerator.Tests/CustomGenerated/CustomGenerated.cs @@ -0,0 +1,384 @@ +// +// This code was generated by Refitter. +// + + +using Refit; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +using Refitter.Tests.AdditionalFiles.SingeInterface; + +#nullable enable annotations + +namespace Refitter.Tests.CustomGenerated +{ + /// Swagger Petstore - OpenAPI 3.0 + [System.CodeDom.Compiler.GeneratedCode("Refitter", "1.0.0.0")] + public partial interface IApiInCustomGeneratedFolder + { + /// Update an existing pet + /// Update an existing pet by Id + /// Update an existent pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// 405 + /// Validation exception + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Put("/pet")] + Task UpdatePet([Body] Pet body); + + /// Add a new pet to the store + /// Add a new pet to the store + /// Create a new pet in the store + /// Successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/pet")] + Task AddPet([Body] Pet body); + + /// Finds Pets by status + /// Multiple status values can be provided with comma separated strings + /// Status values that need to be considered for filter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid status value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByStatus")] + Task> FindPetsByStatus([Query] Status? status); + + /// Finds Pets by tags + /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + /// Tags to filter by + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid tag value + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/pet/findByTags")] + Task> FindPetsByTags([Query(CollectionFormat.Multi)] IEnumerable tags); + + /// Find pet by ID + /// Returns a single pet + /// ID of pet to return + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Pet not found + /// + /// + /// + [Headers("Accept: application/xml, application/json")] + [Get("/pet/{petId}")] + Task GetPetById(long petId); + + /// Updates a pet in the store with form data + /// ID of pet that needs to be updated + /// Name of pet that needs to be updated + /// Status of pet that needs to be updated + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Post("/pet/{petId}")] + Task UpdatePetWithForm(long petId, [Query] string name, [Query] string status); + + /// Deletes a pet + /// api_key parameter + /// Pet id to delete + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid pet value + /// + /// + /// + [Delete("/pet/{petId}")] + Task DeletePet(long petId, [Header("api_key")] string api_key); + + /// uploads an image + /// ID of pet to update + /// Additional Metadata + /// body parameter + /// + /// A representing the instance containing the result: + /// + /// + /// Status + /// Description + /// + /// + /// 200 + /// successful operation + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/octet-stream")] + [Post("/pet/{petId}/uploadImage")] + Task UploadFile(long petId, [Query] string additionalMetadata, StreamPart body); + + /// Returns pet inventories by status + /// Returns a map of status codes to quantities + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json")] + [Get("/store/inventory")] + Task> GetInventory(); + + /// Place an order for a pet + /// Place a new order in the store + /// body parameter + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 405 + /// Invalid input + /// + /// + /// + [Headers("Accept: application/json", "Content-Type: application/json")] + [Post("/store/order")] + Task PlaceOrder([Body] Order body); + + /// Find purchase order by ID + /// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions + /// ID of order that needs to be fetched + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/store/order/{orderId}")] + Task GetOrderById(long orderId); + + /// Delete purchase order by ID + /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + /// ID of the order that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid ID supplied + /// + /// + /// 404 + /// Order not found + /// + /// + /// + [Delete("/store/order/{orderId}")] + Task DeleteOrder(long orderId); + + /// Create user + /// This can only be done by the logged in user. + /// Created user object + /// successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/json, application/xml", "Content-Type: application/json")] + [Post("/user")] + Task CreateUser([Body] User body); + + /// Creates list of users with given input array + /// Creates list of users with given input array + /// body parameter + /// Successful operation + /// Thrown when the request returns a non-success status code. + [Headers("Accept: application/xml, application/json", "Content-Type: application/json")] + [Post("/user/createWithList")] + Task CreateUsersWithListInput([Body] IEnumerable body); + + /// Logs user into the system + /// The user name for login + /// The password for login in clear text + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username/password supplied + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/login")] + Task LoginUser([Query] string username, [Query] string password); + + /// Logs out current logged in user session + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Get("/user/logout")] + Task LogoutUser(); + + /// Get user by user name + /// The name that needs to be fetched. Use user1 for testing. + /// successful operation + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Headers("Accept: application/json")] + [Get("/user/{username}")] + Task GetUserByName(string username); + + /// Update user + /// This can only be done by the logged in user. + /// name that need to be deleted + /// Update an existent user in the store + /// A that completes when the request is finished. + /// Thrown when the request returns a non-success status code. + [Headers("Content-Type: application/json")] + [Put("/user/{username}")] + Task UpdateUser(string username, [Body] User body); + + /// Delete user + /// This can only be done by the logged in user. + /// The name that needs to be deleted + /// A that completes when the request is finished. + /// + /// Thrown when the request returns a non-success status code: + /// + /// + /// Status + /// Description + /// + /// + /// 400 + /// Invalid username supplied + /// + /// + /// 404 + /// User not found + /// + /// + /// + [Delete("/user/{username}")] + Task DeleteUser(string username); + + } + + +} \ No newline at end of file From 14dc55b1020758eab10925504b3099e4153dde3b Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:02:50 +0200 Subject: [PATCH 10/11] docs: restore disk-writing documentation for source generator --- src/Refitter.SourceGenerator/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Refitter.SourceGenerator/README.md b/src/Refitter.SourceGenerator/README.md index 1bd12ec22..24661b1a7 100644 --- a/src/Refitter.SourceGenerator/README.md +++ b/src/Refitter.SourceGenerator/README.md @@ -4,7 +4,9 @@ Refitter is available as a C# Source Generator that uses the [Refitter.Core](https://github.com/christianhelle/refitter/tree/main/src/Refitter.Core) library for generating a REST API Client using the [Refit](https://github.com/reactiveui/refit) library. Refitter can generate the Refit interface from OpenAPI specifications. Refitter could format the generated Refit interface to be managed by [Apizr](https://www.apizr.net) (v6+) and generate some registration helpers too. -Starting with v2.0.0, the source generator emits code in-memory through Roslyn `AddSource()` instead of writing `.g.cs` files to disk. Use your IDE's generated-files view to inspect the output. If your workflow requires physical generated files for review, commits, or build scripts, use Refitter CLI or Refitter.MSBuild instead. +The Refitter source generator creates a folder called `Generated` in the same location as the `.refitter` file and generates files to disk under the `Generated` folder (can be changed with `outputFolder`). The source generator output should be included in the project and committed to source control. This is done because there is no other way to trigger the Refit source generator to pickup the Refitter generated code + +***(Translation: I couldn't for the life of me figure how to get that to work, sorry)*** ### Installation @@ -185,10 +187,10 @@ The following is an example `.refitter` file using multiple OpenAPI specificatio - `useCancellationTokens` - Use cancellation tokens in the generated methods. Default is `false` - `useIsoDateFormat` - Set to `true` to explicitly format date query string parameters in ISO 8601 standard date format using delimiters (for example: 2023-06-15). Default is `false` - `multipleInterfaces` - Set to `ByEndpoint` to generate an interface for each endpoint, or `ByTag` to group Endpoints by their Tag (like SwaggerUI groups them). -- `outputFolder` - a relative output folder used by Refitter CLI and Refitter.MSBuild. The source generator emits code in-memory and does not write to this folder. Default is `./Generated` -- `outputFilename` - Output filename when used from the CLI tool. For the source generator, this sets the base Roslyn hint name for the in-memory generated source; when omitted it derives from the `.refitter` filename. -- `contractsOutputFolder` - a relative contracts output folder used by Refitter CLI and Refitter.MSBuild. The source generator emits contracts in-memory, so this setting has no effect there. Default is `NULL` -- `generateMultipleFiles` - generates multiple disk files when used by Refitter CLI or Refitter.MSBuild. The source generator currently emits a single in-memory source addition per `.refitter` file, so this does not produce separate physical files there. Default is `false` +- `outputFolder` - a string describing a relative path to a desired output folder. Default is `./Generated` +- `outputFilename` - Output filename. Default is `Output.cs` when used from the CLI tool, otherwise its the .refitter filename. So `Petstore.refitter` becomes `Petstore.cs`. +- `contractsOutputFolder` - a relative contracts output folder. Default is `NULL` +- `generateMultipleFiles` - generates multiple disk files. Default is `false` - `additionalNamespaces` - A collection of additional namespaces to include in the generated file. A use case for this is when you want to reuse contracts from a different namespace than the generated code. Default is empty - `excludeNamespaces` - A collection of regular expressions to exclude namespaces from the generated file. A use case for this is when your project has global usings where these namespaces would be redundant. Default is empty - `includeTags` - A collection of tags to use a filter for including endpoints that contain this tag. From c1013182bbdba168c2bab837a85b0876718a4d41 Mon Sep 17 00:00:00 2001 From: Christian Helle Date: Sun, 14 Jun 2026 23:09:31 +0200 Subject: [PATCH 11/11] fix: skip writing when file content is identical to avoid parallel build locks --- src/Refitter.SourceGenerator/RefitterSourceGenerator.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs b/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs index 65a7d947f..1f4b800b4 100644 --- a/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs +++ b/src/Refitter.SourceGenerator/RefitterSourceGenerator.cs @@ -131,7 +131,13 @@ static void WriteGeneratedFile(string outputPath, string content, List