Azure / autorest.csharp

Extension for AutoRest (https://github.com/Azure/autorest) that generates C# code
MIT License
142 stars 166 forks source link

Multi-Level Inheritance Broken #618

Open mattrhoden opened 4 years ago

mattrhoden commented 4 years ago

Hi, I hope this is the right place to file this bug. I am trying to use autorest to generate an api client for our project. It seems to fail when there's an inheritance structure that's at least 2 levels deep. I found one ticket that shows this issue as being resolved, but I am still able to reproduce this.

https://github.com/Azure/autorest/issues/2430

The command and the result are at the bottom of this ticket. Sorry, even the shortest schema is still kind of long.

Also, I just wanted to point out that the error message looks like it is missing additional information that is supposed to be printed out: Found incompatible property types , for property 'bestFriends' in schema inheritance chain

Version Info Type Extension Name Version
core @autorest/core 3.0.6262
extension @microsoft.azure/autorest.csharp 2.3.84
extension @microsoft.azure/autorest.modeler 2.3.55

Model Structure

    public abstract class Dog : Animal
    {
        [Required]
        public bool Friendly { get; set; }

        public IList<Animal> BestFriends { get; set; }
    }

    public class GreenlandDog : Dog
    {
        public bool IsBoofer { get; set; }
    }

    public class Boxer : Dog
    {
        public bool IsBarker { get; set; }
    }

Generated Schema

{
  "openapi": "3.0.1",
  "info": {
    "title": "My API",
    "version": "v1"
  },
  "paths": {
    "/v4/animals-impacted": {
      "get": {
        "tags": [
          "HomeZoo"
        ],
        "operationId": "GetAnimalsImpactedV4",
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "oneOf": [
                      {
                        "oneOf": [
                          {
                            "$ref": "#/components/schemas/GreenlandDog"
                          },
                          {
                            "$ref": "#/components/schemas/Boxer"
                          }
                        ]
                      },
                      {
                        "$ref": "#/components/schemas/GreenlandDog"
                      },
                      {
                        "$ref": "#/components/schemas/Boxer"
                      }
                    ]
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Animal": {
        "required": [
          "$type",
          "name"
        ],
        "type": "object",
        "properties": {
          "$type": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        },
        "discriminator": {
          "propertyName": "$type"
        }
      },
      "Dog": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Animal"
          },
          {
            "required": [
              "$type",
              "friendly",
              "name"
            ],
            "type": "object",
            "properties": {
              "friendly": {
                "type": "boolean"
              },
              "bestFriends": {
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/GreenlandDog"
                        },
                        {
                          "$ref": "#/components/schemas/Boxer"
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/GreenlandDog"
                    },
                    {
                      "$ref": "#/components/schemas/Boxer"
                    }
                  ]
                },
                "nullable": true
              }
            },
            "discriminator": {
              "propertyName": "$type"
            }
          }
        ]
      },
      "Boxer": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Dog"
          },
          {
            "required": [
              "friendly",
              "name"
            ],
            "type": "object",
            "properties": {
              "isBarker": {
                "type": "boolean"
              },
              "friendly": {
                "type": "boolean"
              },
              "bestFriends": {
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/GreenlandDog"
                        },
                        {
                          "$ref": "#/components/schemas/Boxer"
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/GreenlandDog"
                    },
                    {
                      "$ref": "#/components/schemas/Boxer"
                    }
                  ]
                },
                "nullable": true
              },
              "name": {
                "type": "string"
              }
            }
          }
        ]
      },
      "GreenlandDog": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Dog"
          },
          {
            "required": [
              "friendly",
              "name"
            ],
            "type": "object",
            "properties": {
              "isBoofer": {
                "type": "boolean"
              },
              "friendly": {
                "type": "boolean"
              },
              "bestFriends": {
                "type": "array",
                "items": {
                  "oneOf": [
                    {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/GreenlandDog"
                        },
                        {
                          "$ref": "#/components/schemas/Boxer"
                        }
                      ]
                    },
                    {
                      "$ref": "#/components/schemas/GreenlandDog"
                    },
                    {
                      "$ref": "#/components/schemas/Boxer"
                    }
                  ]
                },
                "nullable": true
              },
              "name": {
                "type": "string"
              }
            }
          }
        ]
      }
    }
  }
}

Command & Result

>autorest --v3 --csharp --input-file=./swagger.json --generate-empty-classes --sync-methods=essential --output-folder=dotnet --namespace=Test.Name.Space
AutoRest code generation utility [cli version: 3.0.6187; node: v12.16.1, max-memory: 8192 gb]
(C) 2018 Microsoft Corporation.
https://aka.ms/autorest
   Loading AutoRest core      'C:\Users\matt.rhoden.HQ\.autorest\@autorest_core@3.0.6262\node_modules\@autorest\core\dist' (3.0.6262)
   Loading AutoRest extension '@microsoft.azure/autorest.csharp' (~2.3.79->2.3.84)
   Loading AutoRest extension '@microsoft.azure/autorest.modeler' (2.3.55->2.3.55)
FATAL: System.InvalidOperationException: Found incompatible property types ,  for property 'bestFriends' in schema inheritance chain
   at AutoRest.Modeler.SchemaResolver.ExpandAllOf(Schema schema) in /opt/vsts/work/1/s/src/SchemaResolver.cs:line 157
   at AutoRest.Modeler.SchemaResolver.Unwrap(Schema schema) in /opt/vsts/work/1/s/src/SchemaResolver.cs:line 75
   at AutoRest.Modeler.SchemaBuilder.BuildServiceType(String serviceTypeName, Boolean required) in /opt/vsts/work/1/s/src/SchemaBuilder.cs:line 35
   at AutoRest.Modeler.SwaggerModeler.BuildCompositeTypes() in /opt/vsts/work/1/s/src/SwaggerModeler.cs:line 348
   at AutoRest.Modeler.SwaggerModeler.Build(ServiceDefinition serviceDefinition) in /opt/vsts/work/1/s/src/SwaggerModeler.cs:line 66
   at AutoRest.Modeler.Program.<ProcessInternal>d__2.MoveNext() in /opt/vsts/work/1/s/src/Program.cs:line 60
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NewPlugin.<Process>d__15.MoveNext()
  Error: Plugin imodeler1 reported failure.
mattrhoden commented 4 years ago

Hi @MiYanni I saw you updated the label. Are there any updates? Please let me know if there's a version I am supposed to be on, needs added or if anything is missing. If there's anything I can do to help, would love to give a hand :raising_hand_man:

MiYanni commented 4 years ago

@mattrhoden We're currently working on v3 of autorest.csharp. Unfortunately, we don't have knowledge of v2, and we don't have any intent on updating v2. v3 is rewritten from the ground up. This scenario works in v3 already, as the depth of the inheritance doesn't make a difference to the new generator. Currently, we're just marking issues for v2 so that when we go to release v3, we can review v2 issues and see if we've covered the scenarios appropriately in v3.

mattrhoden commented 4 years ago

@MiYanni I read about there being a v3 in the works somewhere on the internet, maybe in a different issue. Is there some beta version that I could use?

I have v3 of autorest core installed, but as you can see the extensions pulled down are for v2, despite me specifying --V3 as part of the arguments.

Maybe there's another argument I'm missing? I would be so grateful if you could point out my mistake in the command line.

MiYanni commented 4 years ago

@mattrhoden Currently, v3 is only targeting Azure services. There are many features we're working on supporting, but we're getting closer to having some kind beta release. Right now, we're only working with our immediate team and other Azure service teams in terms of feature priority.

To give a little history, AutoRest Core v3 was built in conjunction with building the AutoRest PowerShell generator (what I helped work on). Since then (which happened last year), all other language teams have been working on generators to work with AutoRest Core v3. As it stands, until packages are released for these new generators, all of the old generators will still be acquired and work with AutoRest Core v3.