petrochenko-pavel-a / raml-js-parser2-issues

0 stars 0 forks source link

Simplify inheritance rules to allow more freedom on multiple inheritance of union types etc #14

Closed VasiliyLysokobylko closed 8 years ago

VasiliyLysokobylko commented 8 years ago

RC1 added a lot of restrictions to how you model, for example, inheritance with the RAML type system. To also allow use cases like multiple inheritance of union types or inherit from an array type, these rules should be change to be more flexible/open. That also introduce simpler rules for any type validation since there are less corner cases.

Here is a perfect example that illustrates the usefulness of, for example, being able to extend from union types and object types at the same moment:

#%RAML 1.0
title: Play with named parameter typing
types:
  lat-long: # lat & long required; mutually exclusive with location
    properties:
      lat: number
      long: number
  loc: # location required; mutually exclusive with lat & long
    properties:
      location:
  paging: # each is optional, not exclusive with anything
    properties:
      start?: number
      page-size?: number
/locations:
  get:
    queryString:
      type: [paging,  lat-long | loc ]
      examples:
        first:
          content:
            start: 2
            lat: 12
            long: 13
        second:
          content:
            start: 2
            page-size: 20
            location: 1,2
        third:  # not valid
          content:
            lat: 12
            location: 2
          strict: false # because it's not valid

Or the following should be valid in RC2 too:

types:
   Number1:
     type: number
     minimum: 4
   Number2:
     type: number
     maximum: 10
   Number3: [ Number1, Number2]

Therefore, the complete set of rules in RC1 can be chimed down to only these few in RC2:

The last rule is very important for the support of union types and inheritance (possible multiple inheritance). So let's clarify that a bit more.

First, any union type is built from a set of parent types which are used to compose it. Lets name these types option types in the future. In the following example:

types:
   DogOrCat: Dog | Cat

DogOrCat union type is composed from two option types Dog , Cat

Now lets review a case with multiple inheritance one more time. Imagine we have the following type definition:

types:
   HomeAnimal: [ HasHome ,  Dog | Cat ]

In this case type HomeAnimal has two base types HasHome and anonymous union type defined by a type expression - Dog | Cat

So testing if the HomeAnimal type is a valid involves taking each of its base types, and checking that a type which is derived type of this type and each of union type option types is a valid type. In this particular case you need to test that types [HasHome, Dog] and [HasHome, Cat] are valid types.

If you are extending from two union types you should do the same for every possible combination for example in this case:

types:
   HomeAnimal: [ HasHome | IsOnFarm ,  Dog | Cat | Parrot ]

In summary, you need to test 6 possible combinations: [HasHome, Dog ], [HasHome, Cat ], [HasHome, Parrot], [IsOnFarm, Dog ], [IsOnFarm, Cat ], and [IsOnFarm, Parrot].

VasiliyLysokobylko commented 8 years ago

https://github.com/raml-org/raml-spec/issues/319