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.76k stars 6.56k forks source link

[BUG] Multilevel inheritance not generated correctly #13023

Open cs-nero opened 2 years ago

cs-nero commented 2 years ago
Description

There is a bug in generating multilevel inheritance. We tested it in several languages, for example typescript or C#. I am using the latest version (6.0.1 JAR).

The generated code looks like the following:

    public partial class WeatherForecast : IEquatable<WeatherForecast>, IValidatableObject
    {

        public WeatherForecast(DateTime date = default(DateTime), int temperatureC = default(int), string summary = default(string), string baseProperty = default(string))
        {
            this.Date = date;
            this.TemperatureC = temperatureC;
            this.Summary = summary;
            this.BaseProperty = baseProperty;
        }

        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public int TemperatureF { get; private set; }

        public bool ShouldSerializeTemperatureF()
        {
            return false;
        }

        public string Summary { get; set; }

        public string BaseProperty { get; set; }

    }

    public partial class WeatherForecastBase : IEquatable<WeatherForecastBase>, IValidatableObject
    {
        public WeatherForecastBase(string baseProperty = default(string))
        {
            this.BaseProperty = baseProperty;
        }

        public string BaseProperty { get; set; }

    }

    public partial class WeatherForecastSub : IEquatable<WeatherForecastSub>, IValidatableObject
    {

        public WeatherForecastSub(string subProperty = default(string), string baseProperty = default(string))
        {
            this.SubProperty = subProperty;
            this.BaseProperty = baseProperty;
        }

        public string SubProperty { get; set; }

        public string BaseProperty { get; set; }

    }

Expected code for the WeatherForecastSub class:

public partial class WeatherForecastSub : IEquatable<WeatherForecastSub>, IValidatableObject
    {

        public WeatherForecastSub(string subProperty = default(string), string baseProperty = default(string), DateTime date = default(DateTime), int temperatureC = default(int), string summary = default(string))
        {
            this.SubProperty = subProperty;
            this.BaseProperty = baseProperty;
            this.Date = date;
            this.TemperatureC = temperatureC;
            this.Summary = summary;
        }

        public string BaseProperty { get; set; }

        public string SubProperty { get; set; }

        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public int TemperatureF { get; private set; }

        public bool ShouldSerializeTemperatureF()
        {
            return false;
        }

        public string Summary { get; set; }

    }

In typescript the code looks like the following:

/**
 * 
 * @export
 * @interface WeatherForecast
 */
export interface WeatherForecast {
    /**
     * 
     * @type {string}
     * @memberof WeatherForecast
     */
    'date'?: string;
    /**
     * 
     * @type {number}
     * @memberof WeatherForecast
     */
    'temperatureC'?: number;
    /**
     * 
     * @type {number}
     * @memberof WeatherForecast
     */
    'temperatureF'?: number;
    /**
     * 
     * @type {string}
     * @memberof WeatherForecast
     */
    'summary'?: string | null;
    /**
     * 
     * @type {string}
     * @memberof WeatherForecast
     */
    'baseProperty'?: string | null;
}
/**
 * 
 * @export
 * @interface WeatherForecastBase
 */
export interface WeatherForecastBase {
    /**
     * 
     * @type {string}
     * @memberof WeatherForecastBase
     */
    'baseProperty'?: string | null;
}
/**
 * 
 * @export
 * @interface WeatherForecastSub
 */
export interface WeatherForecastSub {
    /**
     * 
     * @type {string}
     * @memberof WeatherForecastSub
     */
    'subProperty'?: string | null;
    /**
     * 
     * @type {string}
     * @memberof WeatherForecastSub
     */
    'baseProperty'?: string | null;
}

Expected code for WeatherForecastSub:

export interface WeatherForecastSub {
    /**
     * 
     * @type {string}
     * @memberof WeatherForecast
     */
    'date'?: string;
    /**
     * 
     * @type {number}
     * @memberof WeatherForecast
     */
    'temperatureC'?: number;
    /**
     * 
     * @type {number}
     * @memberof WeatherForecast
     */
    'temperatureF'?: number;
    /**
     * 
     * @type {string}
     * @memberof WeatherForecast
     */
    'summary'?: string | null;
    /**
     * 
     * @type {string}
     * @memberof WeatherForecastSub
     */
    'subProperty'?: string | null;
    /**
     * 
     * @type {string}
     * @memberof WeatherForecastSub
     */
    'baseProperty'?: string | null;
}
OpenAPI declaration file content or url

https://gist.github.com/cs-nero/ed1a23f4d848be5eef37864d4c0b5ab3

Steps to reproduce

Use the following command in your cmd: java -jar .\openapi-generator-cli-6.0.1.jar generate -i swagger.json -g csharp-netcore -o generated --skip-validate-spec

Related issues/PRs

You can see a similar issue here: https://github.com/OpenAPITools/openapi-generator/issues/3058 They say it was fixed, but at least for C# and TypeScript, it's not working.

cs-nero commented 2 months ago

Any answer?

wing328 commented 2 months ago

to have inheritance without using discriminator, please enable REF_AS_PARENT_IN_ALLOF in openapi normalizer: https://github.com/openapitools/openapi-generator/blob/master/docs/customization.md#openapi-normalizer

for allOf and properties in the same level, please enable REFACTOR_ALLOF_WITH_PROPERTIES_ONLY as well