Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for optional parameters via the --optional-nullable-parameters CLI argument #163

Merged
merged 18 commits into from
Sep 21, 2023

Conversation

christianhelle
Copy link
Owner

@christianhelle christianhelle commented Sep 20, 2023

This implements #157

The changes here introduces the new --optional-nullable-parameters command line argument which reorders the method arguments in the generated refit interface and places all nullable parameters at the end so that they are optional

The following OpenAPI spec:

openapi: '3.0.0'
paths:
  /job/{Id}:
    post:
      tags:
      - 'Jobs'
      operationId: 'Update job details'
      description: 'Update the details of the specified job.'
      parameters:
        - in: 'path'
          name: 'Id'
          description: 'Foo Id'
          required: true
          schema:
            type: 'string'
        - in: 'query'
          name: 'Title'
          description: 'Job title'
          nullable: true
          schema:
            type: 'string'
        - in: 'query'
          name: 'Description'
          description: 'Job description'
          nullable: true
          schema:
            type: 'string'
        - in: 'query'
          name: 'Contact'
          description: 'Contact Person'
          nullable: true
          schema:
            type: 'string'
      responses:
        '200':
          description: 'successful operation'

generates the following code:

public partial interface IApiClient
{
    /// <summary>
    /// Update the details of the specified job.
    /// </summary>
    [Post("/job/{Id}")]
    Task UpdateJobDetails(
        [AliasAs("Id")] string id, 
        [Query, AliasAs("Title")] string? title = default, 
        [Query, AliasAs("Description")] string? description = default, 
        [Query, AliasAs("Contact")] string? contact = default, 
        CancellationToken cancellationToken = default);
}

@christianhelle christianhelle added the enhancement New feature, bug fix, or request label Sep 20, 2023
@christianhelle christianhelle self-assigned this Sep 20, 2023
@codecov
Copy link

codecov bot commented Sep 20, 2023

Codecov Report

Merging #163 (3467f6b) into main (65ab097) will decrease coverage by 0.16%.
Report is 1 commits behind head on main.
The diff coverage is 95.16%.

@@            Coverage Diff             @@
##             main     #163      +/-   ##
==========================================
- Coverage   98.41%   98.25%   -0.16%     
==========================================
  Files          39       40       +1     
  Lines        1260     1317      +57     
==========================================
+ Hits         1240     1294      +54     
  Misses          6        6              
- Partials       14       17       +3     
Flag Coverage Δ
unittests 98.25% <95.16%> (-0.16%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Changed Coverage Δ
src/Refitter.Core/ParameterExtractor.cs 93.54% <85.00%> (-4.28%) ⬇️
src/Refitter.Core/RefitGenerator.cs 99.33% <100.00%> (+0.02%) ⬆️
....Tests/Examples/OptionalNullableParametersTests.cs 100.00% <100.00%> (ø)
src/Refitter.Tests/SwaggerPetstoreTests.cs 99.35% <100.00%> (ø)

The updated ParameterExtractor.cs now sorts the parameters and explicitly handles optional and nullable parameters. Changes were made to handle edge cases where these parameters were not treated correctly. A new test file, OptionalNullableParametersTests.cs, was added to confirm that the logic correctly generates nullable and optional parameters.
The respective lines of code in SwaggerPetstoreTests were updated to include a nullable api_key. The change was necessary to reflect the possibility of api_key not being required all the time in the application. This allows greater flexibility and ensures the tests inclusively cover different situations.
A new test case is introduced to check if CancellationToken is being generated last in the code. This is to ensure that our code-generation complies with the standard practices, which suggests to always put CancellationToken as the last parameter in a method. Also, RefitGeneratorSettings has been updated to include a new setting – UseCancellationTokens - to decide whether or not CancellationTokens should be included.
This commit introduces changes in ParameterExtractor.cs. A new method, ReOrderNullableParameters, has been created to reorder parameters based on their nullability. This improves parameter handling by ensuring nullable parameters get defaulted last. Also, the process of adding cancellation tokens is now only undertaken if UseCancellationTokens setting is enabled. This provides better flow control and optimizes performance when this setting is not in use.
Updated parameters reordering method. Now you can control whether to reorder optional parameters to the end of the parameter list via a setting. This adjusts for different coding styles and preferences, allowing users to choose to keep optional parameters mixed in with required ones or list them separately at the end.
This change adds nullable support to both 'Description' and 'Contact' query parameters in ‘OptionalNullableParametersTests.cs’ file. It helps us to test scenarios when these parameters are not provided in the request.
The GetBodyParameterType method now includes 'settings' as a parameter, which allows for better customization when deciding whether or not to apply the 'optional' syntax to a parameter type. The 'settings' object carries configuration options that can tailor the Refit generation process to individual preferences. This is a vital change to increase flexibility and adapt to different user needs.
Change the 'Title' query to be nullable instead of required in OptionalNullableParametersTests.cs to enhance test coverage. An inline data attribute is also added for testing the key 'title', ensuring the API handles nullable parameters appropriately.
The api_key param in SwaggerPetstoreTests was updated to be non-nullable. The original test cases including the nullable api_key were failing due to unexpected null values. The update resolves the appearing test failures.
This commit introduces tests for the OptionalParametersGenerator in the Refitter.SourceGenerator.Tests project. The tests - 'Should_Type_Exist' and 'Can_Resolve_Refit_Interface' - check that the type exists within its correct namespace and tests if the interface can be successfully resolved, respectively. This ensures the functionality of optional parameters in generated calls.
Refactored the SwaggerPetstore naming to include "Interface" suffix for consistency and clarity. The change was necessary to avoid confusion between instances of model classes and interfaces. Additionally, added an interface for SwaggerPetstore that includes optional parameters on each method for more flexible usage. Also removed some unnecessary file naming.
This commit introduces a new setting named 'OptionalNullableParameters'. The new setting gives users the flexibility to generate nullable parameters as optional parameters. This provides additional control over the behavior of the refitting process.
This commit includes a change to the GenerateCommand where it now takes into account optional nullable parameters. This added functionality allows for more flexibility when dealing with nullable parameters. The ability to mark parameters as optional and nullable can help in scenarios where the parameter might not always be required.
Added a new example using '--optional-nullable-parameters' flag in the configuration of Program.cs, to demonstrate how to utilize optional nullable parameters in OpenAPI. This enhancement provides clearer and more complete usage examples for users.
An additional argument '--optional-nullable-parameters' was added to the usage sections of both README.md and Refitter/README.md. This argument allows users to generate nullable parameters as optional parameters in the Refit interface. This update provides necessary flexibility for users generating interfaces from OpenAPI specifications.
The naming and declaration of the interfaces `ISwaggerPetstore` and `ISwaggerPetstoreWithOptionalParameters` in `Refitter.SourceGenerator.Tests\AdditionalFiles\Generated` have been changed. This commit includes renaming of `ISwaggerPetstore` to `ISwaggerPetstoreInterface` and adding `partial` keyword to the declaration of `ISwaggerPetstoreWithOptionalParameters` interface. These changes were necessary to provide more clarity and allow future extensions of the interface.
This commit introduces support for nullable reference types to the RefitGenerator. If the 'OptionalParameters' setting is true, the #nullable directive is added to the generated code. This enhancement has been verified by a new unit test 'Generates_Nullable_Directive' added in the OptionalNullableParametersTests file.
@sonarcloud
Copy link

sonarcloud bot commented Sep 21, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 1 Code Smell

No Coverage information No Coverage information
0.0% 0.0% Duplication

Copy link

@waylonmtz waylonmtz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great!

@christianhelle christianhelle merged commit fefd337 into main Sep 21, 2023
848 of 850 checks passed
@christianhelle christianhelle deleted the optional-nullable-parameters branch September 21, 2023 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature, bug fix, or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Generated nullable query method params are not set to a default value of null
2 participants