OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.95k stars 6.59k forks source link

[BUG][C#] Generated code documentation does not match the JSON #2447

Open albator1932 opened 5 years ago

albator1932 commented 5 years ago

Hi guys,

I've got an issue I didn't have with the swagger-codegen (or even earlier versions of openapi-generator but I can't be sure about the version though), I have models that inherit from an abstract class that contains (among other things) a complex object, here is the corresponding JSON extract (which is valid I believe) :

  "definitions": {
    "Error": {
      "description": "Contains all the information related to an error which has occured.",
      "type": "object",
      "properties": {
        "resultcode": {
          "description": "Specifies the last result status provided by the API.",
          "enum": [
            "OK",            
            ...            
            "InvalidAPIKey"
          ],
          "type": "string",
          "readOnly": true
        },
        "extResultStatus": {
          "description": "Specifies a result code related to an error which occured in an external component.",
          "type": "string",
          "readOnly": true
        },
        "extResultMessage": {
          "description": "Specifies a message which further describes the error.",
          "type": "string",
          "readOnly": true
        },
        "internalErrorId": {
          "description": "Specifies a unique identifier, allowing to easily assess the error.",
          "type": "string",
          "readOnly": true
        }
      }
    },    
    ...
    "ActionResponse": {
      "description": "Represents the response to the action request.",
      "type": "object",
      "properties": {
        "Error": {
          "$ref": "#/definitions/Error",
          "description": "If not null, provides information about an unsuccessful action."
        },
        "RemainingTokens": {
          "format": "int64",
          "description": "Specifies the number of remaining tokens.",
          "type": "integer"
        },
        "Data": {
          "format": "byte",
          "description": "Specifies the data.",
          "type": "string",
          "readOnly": true
        }
      }
    }
  }

And now here is the corresponding generated C# (using the csharp generator with the latest snapshot from today, March 19th, default options). First the ActionResponse class:

/// <summary>
/// Initializes a new instance of the <see cref="ActionResponse" /> class.
/// </summary>
/// <param name="error">error.</param>
/// <param name="remainingTokens">Specifies the number of remaining tokens..</param>
public ActionResponse(Error error = default(Error), long? remainingTokens = default(long?))
{
    this.Error = error;
    this.RemainingTokens = remainingTokens;
}

/// <summary>
/// Gets or Sets Error
/// </summary>
[DataMember(Name="Error", EmitDefaultValue=false)]
public Error Error { get; set; }

/// <summary>
/// Specifies the number of remaining tokens.
/// </summary>
/// <value>Specifies the number of remaining tokens.</value>
[DataMember(Name="RemainingTokens", EmitDefaultValue=false)]
public long? RemainingTokens { get; set; }

/// <summary>
/// Specifies the data of the saved document.
/// </summary>
/// <value>Specifies the data of the saved document.</value>
[DataMember(Name="Data", EmitDefaultValue=false)]
public byte[] Data { get; private set; }       

even though the Error class itself is properly documented in the Error.cs

/// <summary>
/// Contains all the information related to an error which has occurred.
/// </summary>
[DataContract]
public partial class Error : IEquatable<Error>, IValidatableObject
{
}

Previously, the Error member of the ActionResponse would have the same documentation as the Error definition, i.e. <summary>Contains all the information related to an error which has occurred.</summary> instead of summary>Gets or Sets Error</summary> Of course this is only an example to illustrate the issue, the API is much larger and complex so we find this problem in many other places but hopefully you get the idea.

Any idea what has changed and could have caused this?

auto-labeler[bot] commented 5 years ago

👍 Thanks for opening this issue! 🏷 I have applied any labels matching special text in your issue.

The team will review the labels and make any necessary changes.

albator1932 commented 5 years ago

I have checked the /src/main/resources/csharp/modelGeneric.mustache and from what I understand it seems that there's no "description" available so it is replaced by "Gets or Sets X" and that's why the part is missing to, at least according to line 103-106

/// <summary>
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
/// </summary>{{#description}}
/// <value>{{description}}</value>{{/description}}

Oddly enough, for any other member (which are basic types, even inherited) it works normally but it apparently does not when it's a complex object.

The result is

/// <summary>
/// Gets or Sets Error
/// </summary>
[DataMember(Name="Error", EmitDefaultValue=false)]
public Error Error { get; set; }

instead of

/// <summary>
/// Contains all the information related to an error which has occurred.
/// </summary>
/// <value>Contains all the information related to an error which has occurred.</value>
[DataMember(Name="Error", EmitDefaultValue=false)]
public Error Error { get; set; }

Any idea where I should look at?

albator1932 commented 5 years ago

No one to help me on this?

wing328 commented 5 years ago

Sure I can help. Let's have a chat via https://Gitter.im (ID: wing328) or other IM channels that you prefer.

albator1932 commented 5 years ago

Thx, I messaged you on Gitter

wing328 commented 5 years ago

Looks like an issue in Swagger Parser:

[main] INFO  o.o.codegen.DefaultCodegen - debugging Cateogry: class Schema {
    type: null
    format: null
    $ref: #/components/schemas/Category
    description: null
    title: null
    multipleOf: null
    maximum: null
    exclusiveMaximum: null
    minimum: null
    exclusiveMinimum: null
    maxLength: null
    minLength: null
    pattern: null
    maxItems: null
    minItems: null
    uniqueItems: null
    maxProperties: null
    minProperties: null
    required: null
    not: null
    properties: null
    additionalProperties: null
    nullable: null
    readOnly: null
    writeOnly: null
    example: null
    externalDocs: null
    deprecated: null
    discriminator: null
    xml: null
}

description is null even though I put down something as follows:

       category:
         $ref: '#/definitions/Category'
        description: "description testing"
albator1932 commented 5 years ago

I opened the corresponding issue there: https://github.com/swagger-api/swagger-parser/issues/1091

jmini commented 5 years ago

This raises again the question: How should we handle spec that are not following the OpenAPI spec.

Having any property set next to $ref is not a valid OpenAPI document, see reference object

$ref (string) REQUIRED. The reference string. This object cannot be extended with additional properties and any properties added SHALL be ignored.

There is a discussion in https://github.com/OAI/OpenAPI-Specification/issues/556 to change this because I agree with you $ref+ description would make sense.