Skip to content

Commit

Permalink
Merge pull request #181 from christianhelle/multiple-interface-operat…
Browse files Browse the repository at this point in the history
…ion-name-template

Allow method name customization when generating multiple interfaces by endpoint
  • Loading branch information
christianhelle authored Oct 9, 2023
2 parents 074b176 + 6395eb0 commit ad3c83c
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 46 deletions.
44 changes: 23 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,33 +52,35 @@ EXAMPLES:
refitter ./openapi.json --tag Pet --tag Store --tag User
refitter ./openapi.json --match-path '^/pet/.*'
refitter ./openapi.json --no-deprecated-operations
refitter ./openapi.json --operation-name-template '{operationName}Async'
refitter ./openapi.json --optional-nullable-parameters
ARGUMENTS:
[URL or input file] URL or file path to OpenAPI Specification file
OPTIONS:
DEFAULT
-h, --help Prints help information
-s, --settings-file Path to .refitter settings file. Specifying this will ignore all other settings (except for --output)
-n, --namespace GeneratedCode Default namespace to use for generated types
-o, --output Output.cs Path to Output file
--no-auto-generated-header Don't add <auto-generated> header to output file
--no-accept-headers Don't add <Accept> header to output file
--interface-only Don't generate contract types
--use-api-response Return Task<IApiResponse<T>> instead of Task<T>
--internal Set the accessibility of the generated types to 'internal'
--cancellation-tokens Use cancellation tokens
--no-operation-headers Don't generate operation headers
--no-logging Don't log errors or collect telemetry
--additional-namespace Add additional namespace to generated types
--use-iso-date-format Explicitly format date query string parameters in ISO 8601 standard date format using delimiters (2023-06-15)
--multiple-interfaces Generate a Refit interface for each endpoint. May be one of ByEndpoint, ByTag
--match-path Only include Paths that match the provided regular expression. May be set multiple times
--tag Only include Endpoints that contain this tag. May be set multiple times and result in OR'ed evaluation
--skip-validation Skip validation of the OpenAPI specification
--no-deprecated-operations Don't generate deprecated operations
--optional-nullable-parameters Generate nullable parameters as optional parameters
DEFAULT
-h, --help Prints help information
-s, --settings-file Path to .refitter settings file. Specifying this will ignore all other settings (except for --output)
-n, --namespace GeneratedCode Default namespace to use for generated types
-o, --output Output.cs Path to Output file
--no-auto-generated-header Don't add <auto-generated> header to output file
--no-accept-headers Don't add <Accept> header to output file
--interface-only Don't generate contract types
--use-api-response Return Task<IApiResponse<T>> instead of Task<T>
--internal Set the accessibility of the generated types to 'internal'
--cancellation-tokens Use cancellation tokens
--no-operation-headers Don't generate operation headers
--no-logging Don't log errors or collect telemetry
--additional-namespace Add additional namespace to generated types
--use-iso-date-format Explicitly format date query string parameters in ISO 8601 standard date format using delimiters (2023-06-15)
--multiple-interfaces Generate a Refit interface for each endpoint. May be one of ByEndpoint, ByTag
--match-path Only include Paths that match the provided regular expression. May be set multiple times
--tag Only include Endpoints that contain this tag. May be set multiple times and result in OR'ed evaluation
--skip-validation Skip validation of the OpenAPI specification
--no-deprecated-operations Don't generate deprecated operations
--operation-name-template Generate operation names using pattern. When using --multiple-interfaces ByEndpoint, this is name of the Execute() method in the interface
--optional-nullable-parameters Generate nullable parameters as optional parameters
```

To generate code from an OpenAPI specifications file, run the following:
Expand Down
7 changes: 7 additions & 0 deletions src/Refitter.Core/RefitGeneratorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,17 @@ public class RefitGeneratorSettings
[JsonProperty("includeTags")]
public string[] IncludeTags { get; set; } = Array.Empty<string>();

/// <summary>
/// Set to <c>true</c> to generate deprecated operations, otherwise <c>false</c>
/// </summary>
[JsonPropertyName("generateDeprecatedOperations")]
[JsonProperty("generateDeprecatedOperations")]
public bool GenerateDeprecatedOperations { get; set; } = true;

/// <summary>
/// Generate operation names using pattern.
/// When using --multiple-interfaces ByEndpoint, this is name of the Execute() method in the interface.
/// </summary>
[JsonPropertyName("operationNameTemplate")]
[JsonProperty("operationNameTemplate")]
public string? OperationNameTemplate { get; set; }
Expand Down
3 changes: 2 additions & 1 deletion src/Refitter.Core/RefitMultipleInterfaceGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ public override RefitGeneratedCode GenerateCode()
GenerateForMultipartFormData(operationModel, code);
GenerateAcceptHeaders(operations, operation, code);

var methodName = settings.OperationNameTemplate ?? "Execute";
code.AppendLine($"{Separator}{Separator}[{verb}(\"{kv.Key}\")]")
.AppendLine($"{Separator}{Separator}{returnType} Execute({parametersString});")
.AppendLine($"{Separator}{Separator}{returnType} {methodName}({parametersString});")
.AppendLine($"{Separator}}}")
.AppendLine();
}
Expand Down
17 changes: 17 additions & 0 deletions src/Refitter.Tests/SwaggerPetstoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,23 @@ public async Task Can_Generate_Code_GeneratedCode_Attribute(
generateCode.Should().Contain("[System.CodeDom.Compiler.GeneratedCode(\"Refitter\"");
}

[Theory]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreJsonV3, "SwaggerPetstore.json", MultipleInterfaces.ByEndpoint)]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreYamlV3, "SwaggerPetstore.yaml", MultipleInterfaces.ByEndpoint)]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreJsonV2, "SwaggerPetstore.json", MultipleInterfaces.ByEndpoint)]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreYamlV2, "SwaggerPetstore.yaml", MultipleInterfaces.ByEndpoint)]
public async Task Can_Generate_Code_With_Multiple_Interfaces_And_OperationNameTemplate(
SampleOpenSpecifications version,
string filename,
MultipleInterfaces multipleInterfaces)
{
var settings = new RefitGeneratorSettings();
settings.MultipleInterfaces = multipleInterfaces;
settings.OperationNameTemplate = "ExecuteAsync";
var generateCode = await GenerateCode(version, filename, settings);
generateCode.Should().Contain("ExecuteAsync(");
}

[Theory]
[InlineData(SampleOpenSpecifications.SwaggerPetstoreJsonV3, "SwaggerPetstore.json")]
#if !DEBUG
Expand Down
4 changes: 3 additions & 1 deletion src/Refitter/GenerateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ public override ValidationResult Validate(CommandContext context, Settings setti
"is not specified in command line argument");
}

if (!string.IsNullOrWhiteSpace(settings.OperationNameTemplate) && !settings.OperationNameTemplate.Contains("{operationName}"))
if (!string.IsNullOrWhiteSpace(settings.OperationNameTemplate) &&
!settings.OperationNameTemplate.Contains("{operationName}") &&
settings.MultipleInterfaces != MultipleInterfaces.ByEndpoint)
return ValidationResult.Error("'{operationName}' placeholder must be present in operation name template");

if (IsUrl(settings.OpenApiPath!))
Expand Down
Loading

0 comments on commit ad3c83c

Please sign in to comment.