Add support for named intersections
parent
a49624fb6e
commit
29348f75e0
|
@ -49,9 +49,19 @@ const extractors = {
|
|||
|
||||
let type = node.leadingComments && (yield* extractLastPragma(node.leadingComments));
|
||||
|
||||
if (!type) {
|
||||
type = yield node.typeAnnotation;
|
||||
}
|
||||
|
||||
if (type.type === 'record') {
|
||||
type.namespace = yield namespace();
|
||||
yield provide(type);
|
||||
type = type.name;
|
||||
}
|
||||
|
||||
return {
|
||||
name: yield node.key,
|
||||
type: type || (yield node.typeAnnotation),
|
||||
type,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -96,6 +106,12 @@ const extractors = {
|
|||
return null;
|
||||
}
|
||||
|
||||
if (type.type === 'record') {
|
||||
type.namespace = yield namespace();
|
||||
yield provide(type);
|
||||
type = type.name;
|
||||
}
|
||||
|
||||
return {
|
||||
name: yield node.key,
|
||||
type,
|
||||
|
@ -157,6 +173,19 @@ const extractors = {
|
|||
return variants;
|
||||
},
|
||||
|
||||
* IntersectionTypeAnnotation(node) {
|
||||
const schemas = [];
|
||||
|
||||
for (const type of node.types) {
|
||||
const name = yield type;
|
||||
const schema = yield query(name);
|
||||
|
||||
schemas.push(schema);
|
||||
}
|
||||
|
||||
return mergeSchemas(schemas);
|
||||
},
|
||||
|
||||
* NullableTypeAnnotation(node) {
|
||||
return ['null', yield node.typeAnnotation];
|
||||
},
|
||||
|
@ -294,4 +323,37 @@ function makeFullname(schema) {
|
|||
return `${schema.namespace}.${schema.name}`;
|
||||
}
|
||||
|
||||
function mergeSchemas(schemas) {
|
||||
const map = new Map;
|
||||
|
||||
// TODO: overriding?
|
||||
let name = '';
|
||||
|
||||
for (const schema of schemas) {
|
||||
// TODO: enums?
|
||||
assert.equal(schema.type, 'record');
|
||||
|
||||
for (const field of schema.fields) {
|
||||
const stored = map.get(field.name);
|
||||
|
||||
if (stored) {
|
||||
// TODO: what about enums?
|
||||
// TODO: improve checking.
|
||||
assert.equal(stored.type, field.type);
|
||||
continue;
|
||||
}
|
||||
|
||||
map.set(field.name, field);
|
||||
}
|
||||
|
||||
name += '_' + schema.name;
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'record',
|
||||
name,
|
||||
fields: Array.from(map.values()),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = extractors;
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
type A = {a: number};
|
||||
type B = {b: string};
|
||||
type C = {c: boolean};
|
||||
|
||||
type X = A & B;
|
||||
|
||||
type Y = {
|
||||
y: A & B & C,
|
||||
};
|
||||
|
||||
class Z {
|
||||
z: A & C;
|
||||
}
|
||||
|
||||
// ###
|
||||
[
|
||||
{
|
||||
type: 'record',
|
||||
name: 'A',
|
||||
namespace: 'intersections',
|
||||
fields: [{name: 'a', type: 'double'}],
|
||||
},
|
||||
{
|
||||
type: 'record',
|
||||
name: 'B',
|
||||
namespace: 'intersections',
|
||||
fields: [{name: 'b', type: 'string'}],
|
||||
},
|
||||
{
|
||||
type: 'record',
|
||||
name: 'C',
|
||||
namespace: 'intersections',
|
||||
fields: [{name: 'c', type: 'boolean'}],
|
||||
},
|
||||
{
|
||||
type: 'record',
|
||||
name: 'X',
|
||||
namespace: 'intersections',
|
||||
fields: [
|
||||
{name: 'a', type: 'double'},
|
||||
{name: 'b', type: 'string'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'record',
|
||||
name: '_A_B_C',
|
||||
namespace: 'intersections',
|
||||
fields: [
|
||||
{name: 'a', type: 'double'},
|
||||
{name: 'b', type: 'string'},
|
||||
{name: 'c', type: 'boolean'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'record',
|
||||
name: 'Y',
|
||||
namespace: 'intersections',
|
||||
fields: [
|
||||
{name: 'y', type: '_A_B_C'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'record',
|
||||
name: '_A_C',
|
||||
namespace: 'intersections',
|
||||
fields: [
|
||||
{name: 'a', type: 'double'},
|
||||
{name: 'c', type: 'boolean'},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'record',
|
||||
name: 'Z',
|
||||
namespace: 'intersections',
|
||||
fields: [
|
||||
{name: 'z', type: '_A_C'},
|
||||
],
|
||||
},
|
||||
]
|
Loading…
Reference in New Issue