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

Incorrect merging of model classes #4428

Closed
andreaTP opened this issue Apr 1, 2024 · 6 comments · Fixed by #4381
Closed

Incorrect merging of model classes #4428

andreaTP opened this issue Apr 1, 2024 · 6 comments · Fixed by #4381
Assignees
Labels
generator Issues or improvements relater to generation capabilities. type:bug A broken experience
Milestone

Comments

@andreaTP
Copy link
Contributor

andreaTP commented Apr 1, 2024

I'm not sure what is going on here (feel free to rephrase the title accordingly), but there is something wrong happening in a (not so)edge case.
Here you have a minimal reproducer description:

openapi: 3.0.3
info:
  title: A bug reproducer
  version: v1
paths:
  "/one":
    patch:
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ComponentTwo"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ComponentOne"
components:
  schemas:
    WithOne:
      type: object
      properties:
        one:
          type: string
    WithTwo:
      type: object
      properties:
        two:
          type: string
    WithThree:
      type: object
      properties:
        three:
          type: string
    ComponentOne:
      type: object
      allOf:
        - $ref: "#/components/schemas/WithOne"
    ComponentTwo:
      type: object
      allOf:
        - $ref: "#/components/schemas/WithOne"
        - $ref: "#/components/schemas/WithTwo"
        - $ref: "#/components/schemas/WithThree"

Generating code with Kiota we obtain (examples in C# for your convenience but applies to all).

expected:

public class ComponentOne : WithOne, IParsable

not expected:

public class ComponentTwo : WithOne, IParsable 

this is surprising, as it seems that ComponentTwo is being considered equal to ComponentOne for some reason.
The expected output for ComponentTwo should be(code trimmed for clarity):

    public class ComponentTwo : IAdditionalDataHolder, IParsable 
    {
        public IDictionary<string, object> AdditionalData { get; set; }
        public string? One { get; set; }
        public string? Two { get; set; }
        public string? Three { get; set; }

If ComponentOne is not used ComponentTwo gets generated with the expected shape(it took forever to minimize 😅 ).

@darrelmiller
Copy link
Member

Vincent is out this week on vacation. @andrueastman could you investigate?

@andrueastman
Copy link
Member

andrueastman commented Apr 2, 2024

Kiota is building an inheritance index here of a type and the types that depend on it from the allOf and using this as a mean of building the discriminator mapping.

When the WithOne type is created, it tries to build the discriminator mappings (therefore initialize its derived types in the codeDom which are ComponentOne and ComponentTwo) by calling GetCodeTypeForMapping

private CodeType? GetCodeTypeForMapping(OpenApiUrlTreeNode currentNode, string referenceId, CodeNamespace currentNamespace, CodeClass? baseClass, OpenApiSchema currentSchema)

However, when this is done, this is done by passing WithOne as the baseClass parameter (as this is being done from the context of the base class trying to create discriminator therefore assuming there are no other in between the inheritance tree).

To resolve this, the baseClass parameter could maybe be removed and the call to AddModelDeclarationIfDoesntExist will look up the schema and should the correct allOf entry as this is its responsibility.

var codeClass = AddModelDeclarationIfDoesntExist(currentNode, discriminatorSchema, className, GetShortestNamespace(currentNamespace, discriminatorSchema), shouldInherit ? baseClass : null);

@andrueastman andrueastman added type:bug A broken experience generator Issues or improvements relater to generation capabilities. labels Apr 2, 2024
@andrueastman
Copy link
Member

@andreaTP Just to confirm this issue is related to the comment at #4346 (comment)?

@andreaTP
Copy link
Contributor Author

andreaTP commented Apr 2, 2024

Just to confirm this issue is related to the comment at #4346 (comment)?

I have no idea ...

@andrueastman andrueastman added this to the Backlog milestone Apr 3, 2024
@dhirajsb
Copy link

Why is Kiota using inheritance for allOf when the spec explicitly states that it's not allowed? From the spec:

allOf can not be used to "extend" a schema to add more details to it in the sense of object-oriented inheritance. Instances must independently be valid against "all of" the schemas in the allOf. See the section on Extending Closed Schemas for more information.

It's meant to be used to compose types, effectively copying the properties of the base allOf.

@baywet
Copy link
Member

baywet commented Apr 16, 2024

Why is Kiota using inheritance for allOf when the spec explicitly states that it's not allowed? From the spec:

allOf can not be used to "extend" a schema to add more details to it in the sense of object-oriented inheritance. Instances must independently be valid against "all of" the schemas in the allOf. See the section on Extending Closed Schemas for more information.

It's meant to be used to compose types, effectively copying the properties of the base allOf.

Unfortunately this is one of the instances where using a validation specification as an IDL shows limitations. Effectively kiota implements the status quo of "OAS chose to use JSON Schema, lots of OAS specs use allOf to model inheritance even though it wasn't designed for that, people expect that convention to work".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
generator Issues or improvements relater to generation capabilities. type:bug A broken experience
Projects
Archived in project
6 participants