Add support for $ElementType and $PropertyType
parent
87979aa328
commit
c95581329e
|
@ -1,5 +1,6 @@
|
|||
import * as fs from 'fs';
|
||||
import * as pathlib from 'path';
|
||||
import wu from 'wu';
|
||||
import {isNode} from '@babel/types';
|
||||
import type {Node} from '@babel/types';
|
||||
|
||||
|
@ -145,7 +146,8 @@ export default class Collector {
|
|||
return result.type;
|
||||
|
||||
case 'special':
|
||||
const type = result.call(params);
|
||||
const resolve = id => this._findTypeById(id);
|
||||
const type = result.call(params, resolve);
|
||||
|
||||
invariant(type);
|
||||
|
||||
|
@ -160,6 +162,22 @@ export default class Collector {
|
|||
this._query(scope, name, []);
|
||||
}
|
||||
}
|
||||
|
||||
_findTypeById(id: TypeId): Type {
|
||||
// TODO: get rid of the linear search.
|
||||
|
||||
for (const type of this.types) {
|
||||
invariant(type.id);
|
||||
|
||||
const is = type.id.join('::') === id.join('::');
|
||||
|
||||
if (is) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
invariant(false);
|
||||
}
|
||||
}
|
||||
|
||||
function pathToId(path: string): TypeId {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import wu from 'wu';
|
||||
|
||||
import {invariant} from './utils';
|
||||
import type {Type} from './types';
|
||||
import type {Type, TypeId} from './types';
|
||||
|
||||
function object(params: (?Type)[]): ?Type {
|
||||
invariant(params.length === 0);
|
||||
|
@ -30,9 +32,32 @@ function array(params: (?Type)[]): ?Type {
|
|||
};
|
||||
}
|
||||
|
||||
function elemType(params: (?Type)[], resolve: TypeId => Type): ?Type {
|
||||
invariant(params.length === 2);
|
||||
|
||||
const [ref, key] = params;
|
||||
|
||||
invariant(ref && key);
|
||||
invariant(ref.kind === 'reference');
|
||||
|
||||
const record = resolve(ref.to);
|
||||
|
||||
invariant(record.kind === 'record');
|
||||
|
||||
// TODO: support for references.
|
||||
invariant(key.kind === 'literal');
|
||||
invariant(typeof key.value === 'string');
|
||||
|
||||
const field = wu(record.fields).find(field => field.name === key.value);
|
||||
|
||||
return field ? Object.assign({}, (field.value: $FlowFixMe)) : null;
|
||||
}
|
||||
|
||||
export default {
|
||||
Object: object,
|
||||
Buffer: buffer,
|
||||
Array: array,
|
||||
$ReadOnlyArray: array,
|
||||
$PropertyType: elemType,
|
||||
$ElementType: elemType,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type {Node} from '@babel/types';
|
||||
|
||||
import type Scope from './scope';
|
||||
import type {Type} from './types';
|
||||
import type {Type, TypeId} from './types';
|
||||
|
||||
export type Query =
|
||||
| Unknown
|
||||
|
@ -48,7 +48,7 @@ export type Special = {
|
|||
call: SpecialFn,
|
||||
};
|
||||
|
||||
export type SpecialFn = (?Type)[] => ?Type;
|
||||
export type SpecialFn = ((?Type)[], TypeId => Type) => ?Type;
|
||||
|
||||
export type TemplateParam = {
|
||||
name: string,
|
||||
|
|
|
@ -182,6 +182,8 @@ function getTypeName(type: Type): string {
|
|||
case 'string':
|
||||
case 'boolean':
|
||||
return type.kind;
|
||||
case 'literal':
|
||||
return String(type.value);
|
||||
default:
|
||||
invariant(false);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
type X<T> = {
|
||||
x: T | string,
|
||||
};
|
||||
|
||||
type Y<T> = {
|
||||
y: $ElementType<X<boolean>, T>,
|
||||
};
|
||||
|
||||
type Z = $PropertyType<Y<'x'>, 'y'>;
|
||||
|
||||
export {Z};
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"types": [
|
||||
{
|
||||
"id": ["elementType", "X", "boolean"],
|
||||
"kind": "record",
|
||||
"fields": [{
|
||||
"name": "x",
|
||||
"value": {
|
||||
"kind": "union",
|
||||
"variants": [
|
||||
{"kind": "boolean"},
|
||||
{"kind": "string"}
|
||||
]
|
||||
},
|
||||
"required": true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id": ["elementType", "Y", "x"],
|
||||
"kind": "record",
|
||||
"fields": [{
|
||||
"name": "y",
|
||||
"value": {
|
||||
"kind": "union",
|
||||
"variants": [
|
||||
{"kind": "boolean"},
|
||||
{"kind": "string"}
|
||||
]
|
||||
},
|
||||
"required": true
|
||||
}]
|
||||
},
|
||||
{
|
||||
"id": ["elementType", "Z"],
|
||||
"kind": "union",
|
||||
"variants": [
|
||||
{"kind": "boolean"},
|
||||
{"kind": "string"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue