Introduce intermediate representation
parent
777d8a0acd
commit
317f8e6e1c
|
@ -16,3 +16,7 @@ module.use_strict=true
|
||||||
munge_underscores=true
|
munge_underscores=true
|
||||||
include_warnings=true
|
include_warnings=true
|
||||||
unsafe.enable_getters_and_setters=true
|
unsafe.enable_getters_and_setters=true
|
||||||
|
suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe
|
||||||
|
suppress_comment= \\(.\\|\n\\)*\\$FlowIssue
|
||||||
|
suppress_type=$FlowFixMe
|
||||||
|
suppress_type=$FlowIssue
|
||||||
|
|
37
README.md
37
README.md
|
@ -5,43 +5,6 @@
|
||||||
[![Windows Build](https://ci.appveyor.com/api/projects/status/github/loyd/flow2schema?branch=master&svg=true)](https://ci.appveyor.com/project/loyd/flow2schema)
|
[![Windows Build](https://ci.appveyor.com/api/projects/status/github/loyd/flow2schema?branch=master&svg=true)](https://ci.appveyor.com/project/loyd/flow2schema)
|
||||||
[![Coverage Status](https://coveralls.io/repos/github/loyd/flow2schema/badge.svg?branch=master)](https://coveralls.io/r/loyd/flow2schema?branch=master)
|
[![Coverage Status](https://coveralls.io/repos/github/loyd/flow2schema/badge.svg?branch=master)](https://coveralls.io/r/loyd/flow2schema?branch=master)
|
||||||
|
|
||||||
Currently avro is the only supported target.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
Input (`$ cat example.js`):
|
|
||||||
```javascript
|
|
||||||
export interface Foo {
|
|
||||||
foo: string,
|
|
||||||
// $avro long
|
|
||||||
bar: number,
|
|
||||||
opt: ?number,
|
|
||||||
baz: 'one' | 'two',
|
|
||||||
mix: 'one' | 'two' | number,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Output (`$ ./bin/flow2schema example.js`):
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"type": "record",
|
|
||||||
"fields": [
|
|
||||||
{"name": "foo", "type": "string"},
|
|
||||||
{"name": "bar", "type": "double"},
|
|
||||||
{"name": "opt", "type": ["null", "double"]},
|
|
||||||
{"name": "baz", "type": {"type": "enum", "symbols": ["one", "two"]}},
|
|
||||||
{
|
|
||||||
"name": "mix",
|
|
||||||
"type": ["double", {"type": "enum", "symbols": ["one", "two"]}]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"name": "Foo",
|
|
||||||
"namespace": "example"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
* Complete generics support.
|
* Complete generics support.
|
||||||
* Errors and warnings.
|
* Errors and warnings.
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
declare module 'wu' {
|
||||||
|
declare type DeepIterable<U> = Iterable<U | DeepIterable<U>>;
|
||||||
|
declare type Flat<T> = $Call<<U>(Iterable<U> | U) => U, T>;
|
||||||
|
declare type DeepFlat<T> = $Call<<U>(DeepIterable<U> | U) => U, T>;
|
||||||
|
|
||||||
|
declare export default class Wu<T> {
|
||||||
|
static <T>(Iterable<T>): Wu<T>;
|
||||||
|
|
||||||
|
tap(T => mixed): Wu<T>;
|
||||||
|
|
||||||
|
map<U>(T => U): Wu<U>;
|
||||||
|
|
||||||
|
filter(): Wu<$NonMaybeType<T>>;
|
||||||
|
filter(T => boolean): Wu<T>;
|
||||||
|
|
||||||
|
flatten(): Wu<DeepFlat<T>>;
|
||||||
|
flatten(true): Wu<DeepFlat<T>>;
|
||||||
|
flatten(false): Wu<Flat<T>>;
|
||||||
|
|
||||||
|
find(T => boolean): T | void;
|
||||||
|
|
||||||
|
pluck<K: $Keys<T>>(K): Wu<$ElementType<T, K>>;
|
||||||
|
|
||||||
|
toArray(): T[];
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,7 +27,8 @@
|
||||||
"babylon": "^7.0.0-beta.32",
|
"babylon": "^7.0.0-beta.32",
|
||||||
"json-stringify-pretty-compact": "^1.0.4",
|
"json-stringify-pretty-compact": "^1.0.4",
|
||||||
"optimist": "^0.6.1",
|
"optimist": "^0.6.1",
|
||||||
"resolve": "^1.5.0"
|
"resolve": "^1.5.0",
|
||||||
|
"wu": "^2.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.0.0-beta.32",
|
"@babel/cli": "^7.0.0-beta.32",
|
||||||
|
|
|
@ -15,9 +15,9 @@ function run(path: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const {schemas} = collect(path);
|
const {types} = collect(path);
|
||||||
|
|
||||||
console.log(stringify(schemas, {maxLength: 100}));
|
console.log(stringify(types, {maxLength: 100}));
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.error(ex.message);
|
console.error(ex.message);
|
||||||
console.error(ex.stack);
|
console.error(ex.stack);
|
||||||
|
|
|
@ -10,28 +10,24 @@ import declarationGroup from './declarations';
|
||||||
import Module from './module';
|
import Module from './module';
|
||||||
import Scope from './scope';
|
import Scope from './scope';
|
||||||
import Context from './context';
|
import Context from './context';
|
||||||
import {invariant, get, map} from './utils';
|
import {invariant} from './utils';
|
||||||
import type Parser from './parser';
|
import type Parser from './parser';
|
||||||
import type {Schema, Type} from './schema';
|
import type {Type, TypeId} from './types';
|
||||||
|
import type {TemplateParam} from './query';
|
||||||
type InstanceParam = {
|
|
||||||
name: string,
|
|
||||||
value: ?Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VISITOR = Object.assign({}, definitionGroup, declarationGroup);
|
const VISITOR = Object.assign({}, definitionGroup, declarationGroup);
|
||||||
|
|
||||||
export default class Collector {
|
export default class Collector {
|
||||||
+root: string;
|
+root: string;
|
||||||
+parser: Parser;
|
+parser: Parser;
|
||||||
+schemas: Schema[];
|
+types: Type[];
|
||||||
_modules: Map<string, Module>;
|
_modules: Map<string, Module>;
|
||||||
_global: Scope;
|
_global: Scope;
|
||||||
|
|
||||||
constructor(parser: Parser, root: string = '.') {
|
constructor(parser: Parser, root: string = '.') {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.schemas = [];
|
this.types = [];
|
||||||
this._modules = new Map;
|
this._modules = new Map;
|
||||||
this._global = Scope.global(globals);
|
this._global = Scope.global(globals);
|
||||||
}
|
}
|
||||||
|
@ -51,9 +47,9 @@ export default class Collector {
|
||||||
const ast = this.parser.parse(code);
|
const ast = this.parser.parse(code);
|
||||||
|
|
||||||
// TODO: customize it.
|
// TODO: customize it.
|
||||||
const namespace = pathToNamespace(pathlib.relative('.', path));
|
const id = pathToId(path);
|
||||||
|
|
||||||
module = new Module(path, namespace);
|
module = new Module(id, path);
|
||||||
|
|
||||||
const scope = this._global.extend(module);
|
const scope = this._global.extend(module);
|
||||||
|
|
||||||
|
@ -66,7 +62,7 @@ export default class Collector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_freestyle(root: Node, scope: Scope, params: InstanceParam[]) {
|
_freestyle(root: Node, scope: Scope, params: TemplateParam[]) {
|
||||||
const ctx = new Context(this, scope, params);
|
const ctx = new Context(this, scope, params);
|
||||||
|
|
||||||
const iter = traverse(root);
|
const iter = traverse(root);
|
||||||
|
@ -88,7 +84,7 @@ export default class Collector {
|
||||||
let result = scope.query(name, params);
|
let result = scope.query(name, params);
|
||||||
|
|
||||||
// TODO: warning.
|
// TODO: warning.
|
||||||
invariant(result.type !== 'unknown');
|
invariant(result.kind !== 'unknown');
|
||||||
|
|
||||||
// Resulting scope is always the best choice for waiting.
|
// Resulting scope is always the best choice for waiting.
|
||||||
scope = result.scope;
|
scope = result.scope;
|
||||||
|
@ -96,7 +92,7 @@ export default class Collector {
|
||||||
// It's only valid the sequence: E*[CT]?F,
|
// It's only valid the sequence: E*[CT]?F,
|
||||||
// where E - external, C - declaration, T - template, F - definition.
|
// where E - external, C - declaration, T - template, F - definition.
|
||||||
|
|
||||||
switch (result.type) {
|
switch (result.kind) {
|
||||||
case 'external':
|
case 'external':
|
||||||
const modulePath = scope.resolve(result.info.path);
|
const modulePath = scope.resolve(result.info.path);
|
||||||
|
|
||||||
|
@ -110,12 +106,12 @@ export default class Collector {
|
||||||
|
|
||||||
result = module.query(imported, params);
|
result = module.query(imported, params);
|
||||||
|
|
||||||
if (result.type === 'definition') {
|
if (result.kind === 'definition') {
|
||||||
return result.schema;
|
return result.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: reexports.
|
// TODO: reexports.
|
||||||
invariant(result.type === 'declaration' || result.type === 'template');
|
invariant(result.kind === 'declaration' || result.kind === 'template');
|
||||||
|
|
||||||
scope = result.scope;
|
scope = result.scope;
|
||||||
name = result.name;
|
name = result.name;
|
||||||
|
@ -125,26 +121,26 @@ export default class Collector {
|
||||||
case 'template':
|
case 'template':
|
||||||
const tmplParams = [];
|
const tmplParams = [];
|
||||||
|
|
||||||
if (result.type === 'template') {
|
if (result.kind === 'template') {
|
||||||
for (const [i, p] of result.params.entries()) {
|
for (const [i, p] of result.params.entries()) {
|
||||||
tmplParams.push({
|
tmplParams.push({
|
||||||
name: p.name,
|
name: p.name,
|
||||||
value: params[i] === undefined ? p.default : params[i],
|
value: params[i] === undefined ? p.value : params[i],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invariant(result.type === 'declaration' || result.type === 'template');
|
invariant(result.kind === 'declaration' || result.kind === 'template');
|
||||||
|
|
||||||
this._freestyle(result.node, scope, tmplParams);
|
this._freestyle(result.node, scope, tmplParams);
|
||||||
|
|
||||||
result = scope.query(name, params);
|
result = scope.query(name, params);
|
||||||
|
|
||||||
invariant(result.type === 'definition');
|
invariant(result.kind === 'definition');
|
||||||
|
|
||||||
// Fallthrough.
|
// Fallthrough.
|
||||||
case 'definition':
|
case 'definition':
|
||||||
return result.schema;
|
return result.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
invariant(false);
|
invariant(false);
|
||||||
|
@ -157,14 +153,14 @@ export default class Collector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function pathToNamespace(path: string): string {
|
function pathToId(path: string): TypeId {
|
||||||
const pathObj = pathlib.parse(path);
|
const relPath = pathlib.relative('.', path);
|
||||||
|
const pathObj = pathlib.parse(relPath);
|
||||||
|
|
||||||
return pathlib.format({
|
return pathlib.format({
|
||||||
dir: pathObj.dir,
|
dir: pathObj.dir,
|
||||||
name: pathObj.name,
|
name: pathObj.name,
|
||||||
})
|
})
|
||||||
// TODO: replace invalid chars.
|
// TODO: replace invalid chars.
|
||||||
.split(pathlib.sep)
|
.split(pathlib.sep);
|
||||||
.join('.');
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,23 @@
|
||||||
|
import wu from 'wu';
|
||||||
import type {Node} from '@babel/types';
|
import type {Node} from '@babel/types';
|
||||||
|
|
||||||
import Scope from './scope';
|
import Scope from './scope';
|
||||||
import Collector from './collector';
|
import Collector from './collector';
|
||||||
import {invariant, get, map} from './utils';
|
import {invariant} from './utils';
|
||||||
import type {Schema, Type, ComplexType} from './schema';
|
import type {Type} from './types';
|
||||||
import type {TemplateParam, ExternalInfo} from './query';
|
import type {TemplateParam, ExternalInfo} from './query';
|
||||||
|
|
||||||
type InstanceParam = {
|
|
||||||
name: string,
|
|
||||||
value: ?Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class Context {
|
export default class Context {
|
||||||
_collector: Collector;
|
_collector: Collector;
|
||||||
_scope: Scope;
|
_scope: Scope;
|
||||||
_params: InstanceParam[];
|
_params: TemplateParam[];
|
||||||
|
|
||||||
constructor(collector: Collector, scope: Scope, params: InstanceParam[]) {
|
constructor(collector: Collector, scope: Scope, params: TemplateParam[]) {
|
||||||
this._collector = collector;
|
this._collector = collector;
|
||||||
this._scope = scope;
|
this._scope = scope;
|
||||||
this._params = params;
|
this._params = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
get namespace(): string {
|
|
||||||
return this._scope.namespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
freestyle(node: Node) {
|
freestyle(node: Node) {
|
||||||
this._collector._freestyle(node, this._scope, this._params);
|
this._collector._freestyle(node, this._scope, this._params);
|
||||||
}
|
}
|
||||||
|
@ -34,26 +26,18 @@ export default class Context {
|
||||||
this._scope.addDeclaration(name, node, params || []);
|
this._scope.addDeclaration(name, node, params || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
define(name: string, type: ComplexType, declared: boolean = true): Schema {
|
define(name: string, type: Type, declared: boolean = true): Type {
|
||||||
// TODO: dirty support for intersections.
|
|
||||||
const _name = type.name != null ? type.name : name;
|
|
||||||
|
|
||||||
const schema: $FlowFixMe = Object.assign({}, type, {
|
|
||||||
name,
|
|
||||||
namespace: this._scope.namespace,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (declared && this._params.length > 0) {
|
if (declared && this._params.length > 0) {
|
||||||
schema.name = generateGenericName(name, this._params);
|
const params = wu(this._params).pluck('value').toArray();
|
||||||
|
|
||||||
this._scope.addInstance(name, schema, map(this._params, get('value')));
|
this._scope.addInstance(name, type, params);
|
||||||
} else {
|
} else {
|
||||||
this._scope.addDefinition(schema, declared);
|
this._scope.addDefinition(name, type, declared);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._collector.schemas.push(schema);
|
this._collector.types.push(type);
|
||||||
|
|
||||||
return schema;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
external(external: ExternalInfo) {
|
external(external: ExternalInfo) {
|
||||||
|
@ -65,7 +49,7 @@ export default class Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
query(name: string, params: ?(?Type)[]): Type {
|
query(name: string, params: ?(?Type)[]): Type {
|
||||||
const param = this._params.find(p => p.name === name);
|
const param = wu(this._params).find(p => p.name === name);
|
||||||
|
|
||||||
if (param) {
|
if (param) {
|
||||||
// TODO: warning about missing param.
|
// TODO: warning about missing param.
|
||||||
|
@ -86,14 +70,3 @@ export default class Context {
|
||||||
this._scope = this._scope.parent;
|
this._scope = this._scope.parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateGenericName(base: string, params: InstanceParam[]): string {
|
|
||||||
let name = base + '_';
|
|
||||||
|
|
||||||
for (const {value} of params) {
|
|
||||||
invariant(typeof value === 'string');
|
|
||||||
name += '_' + value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// flow#5376.
|
import wu from 'wu';
|
||||||
|
|
||||||
|
// @see flow#5376.
|
||||||
import type {
|
import type {
|
||||||
Block, ClassDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, Identifier,
|
Block, ClassDeclaration, ExportDefaultDeclaration, ExportNamedDeclaration, Identifier,
|
||||||
ImportDeclaration, ImportDefaultSpecifier, ImportSpecifier, InterfaceDeclaration,
|
ImportDeclaration, ImportDefaultSpecifier, ImportSpecifier, InterfaceDeclaration,
|
||||||
|
@ -12,7 +14,7 @@ import {
|
||||||
isStringLiteral, isTypeAlias, isVariableDeclaration,
|
isStringLiteral, isTypeAlias, isVariableDeclaration,
|
||||||
} from '@babel/types';
|
} from '@babel/types';
|
||||||
|
|
||||||
import {invariant, map, filter} from './utils';
|
import {invariant} from './utils';
|
||||||
import Context from './context';
|
import Context from './context';
|
||||||
import type {ExternalInfo, TemplateParam} from './query';
|
import type {ExternalInfo, TemplateParam} from './query';
|
||||||
|
|
||||||
|
@ -146,7 +148,10 @@ function extractCommonjsNamedExternals<+T: Node>(nodes: T[], path: string): Exte
|
||||||
path,
|
path,
|
||||||
});
|
});
|
||||||
|
|
||||||
return map(filter(nodes, pred), make);
|
return wu(nodes)
|
||||||
|
.filter(pred)
|
||||||
|
.map(make)
|
||||||
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -201,7 +206,7 @@ function processDeclaration(ctx: Context, node: Declaration) {
|
||||||
|
|
||||||
// TODO: do it only for "all"-mode.
|
// TODO: do it only for "all"-mode.
|
||||||
if (isClassDeclaration(node)) {
|
if (isClassDeclaration(node)) {
|
||||||
const methods = filter(node.body.body, isClassMethod);
|
const methods = wu(node.body.body).filter(isClassMethod).toArray();
|
||||||
|
|
||||||
for (const method of methods) {
|
for (const method of methods) {
|
||||||
ctx.freestyle(method);
|
ctx.freestyle(method);
|
||||||
|
@ -214,10 +219,13 @@ function processDeclaration(ctx: Context, node: Declaration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function extractTemplateParams(node: TypeParameterDeclaration): TemplateParam[] {
|
function extractTemplateParams(node: TypeParameterDeclaration): TemplateParam[] {
|
||||||
return map(node.params, param => ({
|
return wu(node.params)
|
||||||
name: param.name,
|
.map(param => ({
|
||||||
default: null,
|
name: param.name,
|
||||||
}));
|
// TODO: default params.
|
||||||
|
value: null,
|
||||||
|
}))
|
||||||
|
.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
// flow#5376.
|
import wu from 'wu';
|
||||||
|
|
||||||
|
// @see flow#5376.
|
||||||
import type {
|
import type {
|
||||||
ArrayTypeAnnotation, ClassDeclaration, ClassProperty, Comment, FlowTypeAnnotation,
|
ArrayTypeAnnotation, ClassDeclaration, ClassProperty, Comment, FlowTypeAnnotation,
|
||||||
GenericTypeAnnotation, InterfaceDeclaration, IntersectionTypeAnnotation, TypeAlias,
|
GenericTypeAnnotation, InterfaceDeclaration, IntersectionTypeAnnotation, TypeAlias,
|
||||||
UnionTypeAnnotation, NullableTypeAnnotation, ObjectTypeIndexer, ObjectTypeProperty,
|
UnionTypeAnnotation, NullableTypeAnnotation, ObjectTypeIndexer, ObjectTypeProperty,
|
||||||
StringLiteralTypeAnnotation,
|
StringLiteralTypeAnnotation, ObjectTypeAnnotation,
|
||||||
} from '@babel/types';
|
} from '@babel/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -13,98 +15,104 @@ import {
|
||||||
import Context from './context';
|
import Context from './context';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Schema, Type, ReferenceType, ComplexType, RecordType, FixedType,
|
Type, RecordType, Field, ArrayType, TupleType, MapType, UnionType, IntersectionType,
|
||||||
FieldType, ArrayType, MapType, UnionType, EnumType,
|
MaybeType, NumberType, StringType, BooleanType, LiteralType, ReferenceType,
|
||||||
} from './schema';
|
} from './types';
|
||||||
|
|
||||||
import {isPrimitiveType, isComplexType, makeFullname, mergeTypes} from './schema';
|
import {extractPragmas} from './pragmas';
|
||||||
import {invariant, compose, last, get, partition, map, filter, filterMap, compact} from './utils';
|
|
||||||
|
import {invariant} from './utils';
|
||||||
|
|
||||||
function processTypeAlias(ctx: Context, node: TypeAlias) {
|
function processTypeAlias(ctx: Context, node: TypeAlias) {
|
||||||
let type = makeType(ctx, node.right);
|
const {name} = node.id;
|
||||||
|
const type = makeType(ctx, node.right);
|
||||||
|
|
||||||
// TODO: support function aliases.
|
// TODO: support function aliases.
|
||||||
invariant(type != null);
|
invariant(type);
|
||||||
// TODO: support top-level unions.
|
|
||||||
invariant(!(type instanceof Array));
|
|
||||||
|
|
||||||
if (typeof type === 'string') {
|
ctx.define(name, type);
|
||||||
type = {type: type};
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.define(node.id.name, type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: type params.
|
// TODO: type params.
|
||||||
function processInterfaceDeclaration(ctx: Context, node: InterfaceDeclaration) {
|
function processInterfaceDeclaration(ctx: Context, node: InterfaceDeclaration) {
|
||||||
let type = makeType(ctx, node.body);
|
const {name} = node.id;
|
||||||
|
const type = makeType(ctx, node.body);
|
||||||
|
|
||||||
invariant(type != null)
|
invariant(type);
|
||||||
invariant(isComplexType(type));
|
|
||||||
|
|
||||||
if (node.extends.length > 0) {
|
if (node.extends.length === 0) {
|
||||||
const types = [];
|
ctx.define(name, type);
|
||||||
|
return;
|
||||||
for (const extend of node.extends) {
|
|
||||||
const name = extend.id.name;
|
|
||||||
const type = ctx.query(name);
|
|
||||||
|
|
||||||
invariant(isComplexType(type));
|
|
||||||
|
|
||||||
types.push((type: $FlowFixMe));
|
|
||||||
}
|
|
||||||
|
|
||||||
types.push((type: $FlowFixMe));
|
|
||||||
|
|
||||||
[, type] = mergeTypes(types);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.define(node.id.name, type);
|
const parts = [];
|
||||||
|
|
||||||
|
for (const extend of node.extends) {
|
||||||
|
const {name} = extend.id;
|
||||||
|
const type = ctx.query(name);
|
||||||
|
|
||||||
|
invariant(type.id);
|
||||||
|
|
||||||
|
parts.push({
|
||||||
|
kind: 'reference',
|
||||||
|
to: type.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
parts.push(type);
|
||||||
|
|
||||||
|
ctx.define(name, {
|
||||||
|
kind: 'intersection',
|
||||||
|
parts,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: type params.
|
// TODO: type params.
|
||||||
function processClassDeclaration(ctx: Context, node: ClassDeclaration) {
|
function processClassDeclaration(ctx: Context, node: ClassDeclaration) {
|
||||||
const props: $FlowFixMe = filter(node.body.body, isClassProperty);
|
const props: $FlowFixMe = wu(node.body.body).filter(isClassProperty).toArray();
|
||||||
|
|
||||||
let type = makeRecord(ctx, props);
|
const {name} = node.id;
|
||||||
|
const type = makeRecord(ctx, props);
|
||||||
|
|
||||||
if (node.superClass) {
|
if (!node.superClass) {
|
||||||
// TODO: warning about expressions here.
|
ctx.define(name, type);
|
||||||
invariant(isIdentifier(node.superClass));
|
return;
|
||||||
|
|
||||||
const {name} = node.superClass;
|
|
||||||
const superSchema = ctx.query(name);
|
|
||||||
|
|
||||||
invariant(isComplexType(superSchema));
|
|
||||||
|
|
||||||
[, type] = mergeTypes([(superSchema: $FlowFixMe), (type: $FlowFixMe)]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.define(node.id.name, type);
|
// TODO: warning about expressions here.
|
||||||
|
invariant(isIdentifier(node.superClass));
|
||||||
|
|
||||||
|
const base = ctx.query(node.superClass.name);
|
||||||
|
|
||||||
|
invariant(base.id);
|
||||||
|
|
||||||
|
const baseRef = {
|
||||||
|
kind: 'reference',
|
||||||
|
to: base.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.define(name, {
|
||||||
|
kind: 'intersection',
|
||||||
|
parts: [baseRef, type],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeType(ctx: Context, node: FlowTypeAnnotation): ?Type {
|
function makeType(ctx: Context, node: FlowTypeAnnotation): ?Type {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case 'NullLiteralTypeAnnotation':
|
case 'NullLiteralTypeAnnotation':
|
||||||
return 'null';
|
return {kind: 'literal', value: null};
|
||||||
case 'BooleanTypeAnnotation':
|
case 'BooleanTypeAnnotation':
|
||||||
return 'boolean';
|
return {kind: 'boolean'};
|
||||||
case 'NumberTypeAnnotation':
|
case 'NumberTypeAnnotation':
|
||||||
return 'double';
|
return {kind: 'number', repr: 'f64'};
|
||||||
case 'StringTypeAnnotation':
|
case 'StringTypeAnnotation':
|
||||||
return 'string';
|
return {kind: 'string'};
|
||||||
case 'TypeAnnotation':
|
case 'TypeAnnotation':
|
||||||
return makeType(ctx, node.typeAnnotation);
|
return makeType(ctx, node.typeAnnotation);
|
||||||
case 'NullableTypeAnnotation':
|
case 'NullableTypeAnnotation':
|
||||||
return makeNullable(ctx, node);
|
return makeMaybe(ctx, node);
|
||||||
case 'ObjectTypeAnnotation':
|
case 'ObjectTypeAnnotation':
|
||||||
const map = makeMap(ctx, node.indexers);
|
return makeComplexType(ctx, node);
|
||||||
const record = makeRecord(ctx, node.properties);
|
|
||||||
|
|
||||||
// TODO: warning about this.
|
|
||||||
invariant(!map || record.fields.length === 0);
|
|
||||||
|
|
||||||
return map || record;
|
|
||||||
case 'ArrayTypeAnnotation':
|
case 'ArrayTypeAnnotation':
|
||||||
return makeArrayType(ctx, node);
|
return makeArrayType(ctx, node);
|
||||||
case 'UnionTypeAnnotation':
|
case 'UnionTypeAnnotation':
|
||||||
|
@ -112,50 +120,85 @@ function makeType(ctx: Context, node: FlowTypeAnnotation): ?Type {
|
||||||
case 'IntersectionTypeAnnotation':
|
case 'IntersectionTypeAnnotation':
|
||||||
return makeIntersection(ctx, node);
|
return makeIntersection(ctx, node);
|
||||||
case 'StringLiteralTypeAnnotation':
|
case 'StringLiteralTypeAnnotation':
|
||||||
return makeEnum(node);
|
return {kind: 'literal', value: node.value};
|
||||||
case 'GenericTypeAnnotation':
|
case 'GenericTypeAnnotation':
|
||||||
return makeReference(ctx, node);
|
return makeReference(ctx, node);
|
||||||
case 'FunctionTypeAnnotation':
|
case 'FunctionTypeAnnotation':
|
||||||
return null;
|
return null;
|
||||||
default:
|
default:
|
||||||
invariant(false, `Unknown type: ${node.type}`);
|
invariant(false, `Unknown node: ${node.type}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeNullable(ctx: Context, node: NullableTypeAnnotation): ?UnionType {
|
function makeMaybe(ctx: Context, node: NullableTypeAnnotation): ?MaybeType {
|
||||||
const type = makeType(ctx, node.typeAnnotation);
|
const type = makeType(ctx, node.typeAnnotation);
|
||||||
|
|
||||||
if (type == null) {
|
if (!type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['null', type];
|
return {
|
||||||
|
kind: 'maybe',
|
||||||
|
value: type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeComplexType(ctx: Context, node: ObjectTypeAnnotation): Type {
|
||||||
|
const maps = wu(node.indexers)
|
||||||
|
.map(node => makeMap(ctx, node))
|
||||||
|
.filter()
|
||||||
|
.toArray();
|
||||||
|
|
||||||
|
const record = makeRecord(ctx, node.properties);
|
||||||
|
|
||||||
|
if (maps.length === 1 && record.fields.length === 0) {
|
||||||
|
return maps[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maps.length === 0) {
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = record.fields.length > 0 ? [record, ...maps] : maps;
|
||||||
|
|
||||||
|
return {
|
||||||
|
kind: 'intersection',
|
||||||
|
parts,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeRecord<T: ObjectTypeProperty | ClassProperty>(ctx: Context, nodes: T[]): RecordType {
|
function makeRecord<T: ObjectTypeProperty | ClassProperty>(ctx: Context, nodes: T[]): RecordType {
|
||||||
const fields = compact(map(nodes, node => makeField(ctx, node)));
|
const fields = wu(nodes)
|
||||||
|
.map(node => makeField(ctx, node))
|
||||||
|
.filter()
|
||||||
|
.toArray();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'record',
|
kind: 'record',
|
||||||
fields,
|
fields,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?FieldType {
|
function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Field {
|
||||||
// $FlowFixMe
|
if ((node: $FlowIssue<3129>).static) {
|
||||||
if (node.static) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let type = null;
|
let type = null;
|
||||||
|
|
||||||
if (node.leadingComments) {
|
if (node.leadingComments) {
|
||||||
const pragmas = extractPragmas(node.leadingComments);
|
const pragma = (wu: $FlowIssue<4431>)(node.leadingComments)
|
||||||
|
.pluck('value')
|
||||||
|
.map(extractPragmas)
|
||||||
|
.flatten()
|
||||||
|
.find(pragma => pragma.kind === 'type');
|
||||||
|
|
||||||
type = last(pragmas);
|
if (pragma) {
|
||||||
|
type = pragma.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == null) {
|
if (!type) {
|
||||||
const value = isObjectTypeProperty(node) ? node.value : node.typeAnnotation;
|
const value = isObjectTypeProperty(node) ? node.value : node.typeAnnotation;
|
||||||
|
|
||||||
// TODO: no type annotation for the class property.
|
// TODO: no type annotation for the class property.
|
||||||
|
@ -164,17 +207,10 @@ function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Fie
|
||||||
type = makeType(ctx, value);
|
type = makeType(ctx, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == null) {
|
if (!type) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isComplexType(type) && type.type === 'record') {
|
|
||||||
const name = (type: $FlowFixMe).name;
|
|
||||||
ctx.define(name, type, false);
|
|
||||||
type = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: support optional fields.
|
|
||||||
// TODO: warning about computed properties.
|
// TODO: warning about computed properties.
|
||||||
|
|
||||||
invariant(isObjectTypeProperty(node) || !node.computed);
|
invariant(isObjectTypeProperty(node) || !node.computed);
|
||||||
|
@ -182,30 +218,22 @@ function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Fie
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: node.key.name,
|
name: node.key.name,
|
||||||
type,
|
value: type,
|
||||||
|
required: node.optional == null || !node.optional,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeMap(ctx: Context, nodes: ObjectTypeIndexer[]): ?MapType {
|
function makeMap(ctx: Context, node: ObjectTypeIndexer): ?MapType {
|
||||||
if (nodes.length === 0) {
|
const keys = makeType(ctx, node.key);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: what to do in this case?
|
|
||||||
invariant(nodes.length === 1);
|
|
||||||
|
|
||||||
const node = nodes[0];
|
|
||||||
|
|
||||||
invariant(makeType(ctx, node.key) === 'string');
|
|
||||||
|
|
||||||
const values = makeType(ctx, node.value);
|
const values = makeType(ctx, node.value);
|
||||||
|
|
||||||
if (values == null) {
|
if (!(keys && values)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'map',
|
kind: 'map',
|
||||||
|
keys,
|
||||||
values,
|
values,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -213,151 +241,68 @@ function makeMap(ctx: Context, nodes: ObjectTypeIndexer[]): ?MapType {
|
||||||
function makeArrayType(ctx: Context, node: ArrayTypeAnnotation): ?ArrayType {
|
function makeArrayType(ctx: Context, node: ArrayTypeAnnotation): ?ArrayType {
|
||||||
const items = makeType(ctx, node.elementType);
|
const items = makeType(ctx, node.elementType);
|
||||||
|
|
||||||
if (items == null) {
|
if (!items) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'array',
|
kind: 'array',
|
||||||
items,
|
items,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeUnionType(ctx: Context, node: UnionTypeAnnotation): ?(UnionType | EnumType) {
|
function makeUnionType(ctx: Context, node: UnionTypeAnnotation): ?UnionType {
|
||||||
// TODO: flatten variants.
|
const variants = wu(node.types)
|
||||||
// TODO: refactor it.
|
.map(node => makeType(ctx, node))
|
||||||
|
.filter()
|
||||||
let [symbols, variants] = partition(node.types, isStringLiteralTypeAnnotation);
|
.toArray();
|
||||||
|
|
||||||
// $FlowFixMe
|
|
||||||
symbols = map(symbols, get('value'));
|
|
||||||
variants = compact(map(variants, node => makeType(ctx, node)));
|
|
||||||
|
|
||||||
if (symbols.length > 0) {
|
|
||||||
const enumeration: EnumType = {
|
|
||||||
type: 'enum',
|
|
||||||
symbols,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (variants.length === 0) {
|
|
||||||
return enumeration;
|
|
||||||
}
|
|
||||||
|
|
||||||
variants.push(enumeration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variants.length === 0) {
|
if (variants.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return variants;
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeIntersection(ctx: Context, node: IntersectionTypeAnnotation): ?Type {
|
|
||||||
const types = [];
|
|
||||||
|
|
||||||
// TODO: refactor it.
|
|
||||||
for (const typeNode of node.types) {
|
|
||||||
const type = makeType(ctx, typeNode);
|
|
||||||
|
|
||||||
if (type == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: support arbitrary types, not only references.
|
|
||||||
invariant(typeof type === 'string');
|
|
||||||
|
|
||||||
const queried = ctx.query(type);
|
|
||||||
|
|
||||||
invariant(isComplexType(queried));
|
|
||||||
|
|
||||||
types.push((queried: $FlowFixMe));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (types.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [name, intersection] = mergeTypes(types);
|
|
||||||
|
|
||||||
// TODO: dirty support for intersections.
|
|
||||||
(intersection: $FlowFixMe).name = name;
|
|
||||||
|
|
||||||
return intersection;
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeEnum(node: StringLiteralTypeAnnotation): EnumType {
|
|
||||||
return {
|
return {
|
||||||
type: 'enum',
|
kind: 'union',
|
||||||
symbols: [node.value],
|
variants,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeReference(ctx: Context, node: GenericTypeAnnotation): ReferenceType {
|
function makeIntersection(ctx: Context, node: IntersectionTypeAnnotation): ?Type {
|
||||||
const {name} = node.id;
|
// TODO: warning about nulls.
|
||||||
const params = node.typeParameters && map(node.typeParameters.params, n => makeType(ctx, n));
|
const parts = wu(node.types)
|
||||||
|
.map(node => makeType(ctx, node))
|
||||||
|
.filter()
|
||||||
|
.toArray();
|
||||||
|
|
||||||
const type = ctx.query(name, params);
|
if (parts.length === 0) {
|
||||||
|
|
||||||
if (typeof type === 'string') {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: generalized it.
|
|
||||||
if ((type: $FlowFixMe).$unwrap) {
|
|
||||||
invariant(typeof type.type === 'string');
|
|
||||||
|
|
||||||
return type.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
invariant(isComplexType(type));
|
|
||||||
|
|
||||||
if (type.namespace === ctx.namespace) {
|
|
||||||
return (type: $FlowFixMe).name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return makeFullname((type: $FlowFixMe));
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractPragmas(comments: Comment[]): Type[] {
|
|
||||||
return filterMap(comments, compose(get('value'), extractPragma));
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractPragma(text: string): ?Type {
|
|
||||||
const marker = '$avro ';
|
|
||||||
|
|
||||||
const value = text.trimLeft();
|
|
||||||
|
|
||||||
if (!value.startsWith(marker)) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pragma = value.slice(marker.length).trim();
|
if (parts.length === 1) {
|
||||||
|
return parts[0];
|
||||||
|
}
|
||||||
|
|
||||||
return parsePragma(pragma);
|
return {
|
||||||
|
kind: 'intersection',
|
||||||
|
parts,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function parsePragma(pragma: string): Type {
|
function makeReference(ctx: Context, node: GenericTypeAnnotation): ?Type {
|
||||||
let [type, arg] = pragma.split(/\s+/);
|
const {name} = node.id;
|
||||||
|
const params = node.typeParameters
|
||||||
|
&& wu(node.typeParameters.params).map(n => makeType(ctx, n)).toArray();
|
||||||
|
|
||||||
if (isPrimitiveType(type)) {
|
const type = ctx.query(name, params);
|
||||||
invariant(arg == null);
|
|
||||||
|
|
||||||
|
if (!type.id) {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'fixed') {
|
return {
|
||||||
arg = Number(arg);
|
kind: 'reference',
|
||||||
|
to: type.id,
|
||||||
invariant(Number.isInteger(arg));
|
};
|
||||||
|
|
||||||
return ({
|
|
||||||
type: 'fixed',
|
|
||||||
size: arg,
|
|
||||||
}: FixedType);
|
|
||||||
}
|
|
||||||
|
|
||||||
invariant(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
name: 'Buffer',
|
id: ['Buffer'],
|
||||||
type: 'bytes',
|
kind: 'record',
|
||||||
$unwrap: true,
|
fields: [],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -2,24 +2,29 @@ import * as pathlib from 'path';
|
||||||
import * as resolve from 'resolve';
|
import * as resolve from 'resolve';
|
||||||
|
|
||||||
import type Scope from './scope';
|
import type Scope from './scope';
|
||||||
import type {Schema, Type} from './schema';
|
import type {Type, TypeId} from './types';
|
||||||
import type {Query} from './query';
|
import type {Query} from './query';
|
||||||
|
|
||||||
export default class Module {
|
export default class Module {
|
||||||
|
+id: TypeId;
|
||||||
+path: string;
|
+path: string;
|
||||||
+namespace: string;
|
|
||||||
_scopeCount: number;
|
_scopeCount: number;
|
||||||
_exports: Map<?string, [Scope, string]>;
|
_exports: Map<?string, [Scope, string]>;
|
||||||
|
|
||||||
constructor(path: string, namespace: string) {
|
constructor(id: TypeId, path: string) {
|
||||||
|
this.id = id;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.namespace = namespace;
|
|
||||||
this._scopeCount = 0;
|
this._scopeCount = 0;
|
||||||
this._exports = new Map;
|
this._exports = new Map;
|
||||||
}
|
}
|
||||||
|
|
||||||
generateScopeId(): number {
|
generateScopeId(): TypeId {
|
||||||
return this._scopeCount++;
|
if (this._scopeCount === 0) {
|
||||||
|
++this._scopeCount;
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.id.concat(String(this._scopeCount++));
|
||||||
}
|
}
|
||||||
|
|
||||||
addExport(name: ?string, scope: Scope, reference: string) {
|
addExport(name: ?string, scope: Scope, reference: string) {
|
||||||
|
@ -31,7 +36,7 @@ export default class Module {
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return {
|
return {
|
||||||
type: 'unknown',
|
kind: 'unknown',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import {invariant} from './utils';
|
||||||
|
|
||||||
|
import type {Type} from './types';
|
||||||
|
|
||||||
|
export type Pragma =
|
||||||
|
| TypePragma;
|
||||||
|
|
||||||
|
export type TypePragma = {
|
||||||
|
kind: 'type',
|
||||||
|
value: Type,
|
||||||
|
};
|
||||||
|
|
||||||
|
const PRAGMA_RE = /^\s*@repr\s+\{\s*(.+?)\s*\}\s*$/gm;
|
||||||
|
|
||||||
|
export function extractPragmas(text: string): Pragma[] {
|
||||||
|
const pragmas = [];
|
||||||
|
let match;
|
||||||
|
|
||||||
|
while ((match = PRAGMA_RE.exec(text))) {
|
||||||
|
const repr = match[1];
|
||||||
|
|
||||||
|
invariant(['i32', 'i64', 'u32', 'u64', 'f32', 'f64'].includes(repr));
|
||||||
|
|
||||||
|
const pragma = {
|
||||||
|
kind: 'type',
|
||||||
|
value: {
|
||||||
|
kind: 'number',
|
||||||
|
repr,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pragma) {
|
||||||
|
pragmas.push(pragma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pragmas;
|
||||||
|
}
|
18
src/query.js
18
src/query.js
|
@ -1,7 +1,7 @@
|
||||||
import type {Node} from '@babel/types';
|
import type {Node} from '@babel/types';
|
||||||
|
|
||||||
import type Scope from './scope';
|
import type Scope from './scope';
|
||||||
import type {Schema, Type} from './schema';
|
import type {Type} from './types';
|
||||||
|
|
||||||
export type Query =
|
export type Query =
|
||||||
| Unknown
|
| Unknown
|
||||||
|
@ -11,18 +11,18 @@ export type Query =
|
||||||
| External;
|
| External;
|
||||||
|
|
||||||
export type Unknown = {
|
export type Unknown = {
|
||||||
type: 'unknown',
|
kind: 'unknown',
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Declaration = {
|
export type Declaration = {
|
||||||
type: 'declaration',
|
kind: 'declaration',
|
||||||
name: string,
|
name: string,
|
||||||
node: Node,
|
node: Node,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Template = {
|
export type Template = {
|
||||||
type: 'template',
|
kind: 'template',
|
||||||
name: string,
|
name: string,
|
||||||
params: TemplateParam[],
|
params: TemplateParam[],
|
||||||
instances: Instance[],
|
instances: Instance[],
|
||||||
|
@ -31,25 +31,25 @@ export type Template = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Definition = {
|
export type Definition = {
|
||||||
type: 'definition',
|
kind: 'definition',
|
||||||
schema: Schema,
|
type: Type,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type External = {
|
export type External = {
|
||||||
type: 'external',
|
kind: 'external',
|
||||||
info: ExternalInfo,
|
info: ExternalInfo,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TemplateParam = {
|
export type TemplateParam = {
|
||||||
name: string,
|
name: string,
|
||||||
default: ?Type,
|
value: ?Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Instance = {
|
export type Instance = {
|
||||||
params: (?Type)[],
|
params: (?Type)[],
|
||||||
schema: Schema,
|
type: Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExternalInfo = {
|
export type ExternalInfo = {
|
||||||
|
|
147
src/schema.js
147
src/schema.js
|
@ -1,147 +0,0 @@
|
||||||
import {invariant} from './utils';
|
|
||||||
|
|
||||||
// @see flow#3912.
|
|
||||||
export type Schema =
|
|
||||||
| RecordType & Top
|
|
||||||
| EnumType & Top
|
|
||||||
| ArrayType & Top
|
|
||||||
| MapType & Top
|
|
||||||
// TODO: support top-level unions.
|
|
||||||
//| UnionType & Top
|
|
||||||
| FixedType & Top
|
|
||||||
| WrappedType & Top;
|
|
||||||
|
|
||||||
export type Top = {
|
|
||||||
name: string,
|
|
||||||
namespace?: string,
|
|
||||||
$unwrap?: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Type =
|
|
||||||
| ComplexType
|
|
||||||
| UnionType
|
|
||||||
| PrimitiveType
|
|
||||||
| ReferenceType;
|
|
||||||
|
|
||||||
export type WrappedType = {type: Type};
|
|
||||||
|
|
||||||
export type ComplexType =
|
|
||||||
| RecordType
|
|
||||||
| EnumType
|
|
||||||
| ArrayType
|
|
||||||
| MapType
|
|
||||||
// TODO: unions should be complex types.
|
|
||||||
//| UnionType & Top
|
|
||||||
| FixedType
|
|
||||||
| WrappedType;
|
|
||||||
|
|
||||||
export type PrimitiveType =
|
|
||||||
| 'null'
|
|
||||||
| 'boolean'
|
|
||||||
| 'int'
|
|
||||||
| 'long'
|
|
||||||
| 'float'
|
|
||||||
| 'double'
|
|
||||||
| 'bytes'
|
|
||||||
| 'string';
|
|
||||||
|
|
||||||
export type ReferenceType = string;
|
|
||||||
|
|
||||||
export type RecordType = {
|
|
||||||
type: 'record',
|
|
||||||
fields: FieldType[],
|
|
||||||
};
|
|
||||||
|
|
||||||
export type FieldType = {
|
|
||||||
name: string,
|
|
||||||
type: Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
export type EnumType = {
|
|
||||||
type: 'enum',
|
|
||||||
symbols: string[],
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ArrayType = {
|
|
||||||
type: 'array',
|
|
||||||
items: Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
export type MapType = {
|
|
||||||
type: 'map',
|
|
||||||
values: Type,
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UnionType = Type[];
|
|
||||||
|
|
||||||
export type FixedType = {
|
|
||||||
type: 'fixed',
|
|
||||||
size: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function isPrimitiveType(type: Type): boolean %checks {
|
|
||||||
// Switch operator is not allowed in %checks functions.
|
|
||||||
return type === 'null'
|
|
||||||
|| type === 'int'
|
|
||||||
|| type === 'long'
|
|
||||||
|| type === 'float'
|
|
||||||
|| type === 'double'
|
|
||||||
|| type === 'bytes'
|
|
||||||
|| type === 'string'
|
|
||||||
|| type === 'boolean';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isComplexType(type: Type): boolean %checks {
|
|
||||||
return typeof type !== 'string' && !(type instanceof Array);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeFullname(schema: Top): string {
|
|
||||||
invariant(schema.namespace != null);
|
|
||||||
|
|
||||||
return `${schema.namespace}.${schema.name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mergeTypes<+T: ComplexType & {+name?: string}>(types: T[]): [string, ComplexType] {
|
|
||||||
invariant(types.length > 1);
|
|
||||||
|
|
||||||
if (types.length === 1) {
|
|
||||||
const type = types[0];
|
|
||||||
// TODO: anonymous?
|
|
||||||
invariant(type.name != null);
|
|
||||||
|
|
||||||
return [type.name, (type: $FlowFixMe)];
|
|
||||||
}
|
|
||||||
|
|
||||||
const map = new Map;
|
|
||||||
|
|
||||||
// TODO: overriding?
|
|
||||||
let name = '';
|
|
||||||
|
|
||||||
for (const type of types) {
|
|
||||||
// TODO: enums?
|
|
||||||
invariant(type.type === 'record');
|
|
||||||
|
|
||||||
for (const field of (type: $FlowFixMe).fields) {
|
|
||||||
const stored = map.get(field.name);
|
|
||||||
|
|
||||||
if (stored) {
|
|
||||||
// TODO: what about enums?
|
|
||||||
// TODO: improve checking.
|
|
||||||
invariant(stored.type === field.type);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
map.set(field.name, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: anonymous?
|
|
||||||
name += '_' + (type.name != null ? type.name : 'unnamed');
|
|
||||||
}
|
|
||||||
|
|
||||||
const type = {
|
|
||||||
type: 'record',
|
|
||||||
fields: Array.from(map.values()),
|
|
||||||
};
|
|
||||||
|
|
||||||
return [name, (type: $FlowFixMe)];
|
|
||||||
}
|
|
109
src/scope.js
109
src/scope.js
|
@ -1,46 +1,39 @@
|
||||||
|
import wu from 'wu';
|
||||||
import type {Node} from '@babel/types';
|
import type {Node} from '@babel/types';
|
||||||
|
|
||||||
import {invariant} from './utils';
|
import {invariant, last} from './utils';
|
||||||
import type Module from './module';
|
import type Module from './module';
|
||||||
import type {Schema, Type} from './schema';
|
import type {Type, TypeId} from './types';
|
||||||
import type {Query, Template, TemplateParam, ExternalInfo} from './query';
|
import type {Query, Template, TemplateParam, ExternalInfo} from './query';
|
||||||
|
|
||||||
export default class Scope {
|
export default class Scope {
|
||||||
|
+id: TypeId;
|
||||||
+parent: ?Scope;
|
+parent: ?Scope;
|
||||||
+module: ?Module;
|
+module: ?Module;
|
||||||
+scopeId: ?number;
|
|
||||||
_entries: Map<string, Query>;
|
_entries: Map<string, Query>;
|
||||||
|
|
||||||
static global(schemas: Schema[]) {
|
static global(types: Type[]) {
|
||||||
const global = new Scope(null, null);
|
const global = new Scope(null, null);
|
||||||
|
|
||||||
for (const schema of schemas) {
|
for (const type of types) {
|
||||||
global.addDefinition(schema, false);
|
invariant(type.id);
|
||||||
|
|
||||||
|
const name = last(type.id);
|
||||||
|
invariant(name != null);
|
||||||
|
|
||||||
|
global.addDefinition(name, type, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(parent: ?Scope, module: ?Module) {
|
constructor(parent: ?Scope, module: ?Module) {
|
||||||
|
this.id = module ? module.generateScopeId() : [];
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.module = module;
|
this.module = module;
|
||||||
this.scopeId = module && module.generateScopeId();
|
|
||||||
this._entries = new Map;
|
this._entries = new Map;
|
||||||
}
|
}
|
||||||
|
|
||||||
get namespace(): string {
|
|
||||||
invariant(this.module);
|
|
||||||
|
|
||||||
let namespace = this.module.namespace;
|
|
||||||
|
|
||||||
// Nested scopes.
|
|
||||||
if (this.scopeId != null && this.scopeId > 0) {
|
|
||||||
namespace += '._' + this.scopeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
return namespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
extend(module: ?Module = null): Scope {
|
extend(module: ?Module = null): Scope {
|
||||||
return new Scope(this, module || this.module);
|
return new Scope(this, module || this.module);
|
||||||
}
|
}
|
||||||
|
@ -49,14 +42,14 @@ export default class Scope {
|
||||||
invariant(!this._entries.has(name));
|
invariant(!this._entries.has(name));
|
||||||
|
|
||||||
const entry = params.length > 0 ? {
|
const entry = params.length > 0 ? {
|
||||||
type: 'template',
|
kind: 'template',
|
||||||
name,
|
name,
|
||||||
params,
|
params,
|
||||||
instances: [],
|
instances: [],
|
||||||
node,
|
node,
|
||||||
scope: this,
|
scope: this,
|
||||||
} : {
|
} : {
|
||||||
type: 'declaration',
|
kind: 'declaration',
|
||||||
name,
|
name,
|
||||||
node,
|
node,
|
||||||
scope: this,
|
scope: this,
|
||||||
|
@ -65,28 +58,34 @@ export default class Scope {
|
||||||
this._entries.set(name, entry);
|
this._entries.set(name, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
addInstance(name: string, schema: Schema, params: (?Type)[]) {
|
addInstance(name: string, type: Type, params: (?Type)[]) {
|
||||||
const template = this._entries.get(name);
|
const template = this._entries.get(name);
|
||||||
|
|
||||||
invariant(template);
|
invariant(template);
|
||||||
invariant(template.type === 'template');
|
invariant(template.kind === 'template');
|
||||||
|
|
||||||
template.instances.push({params, schema});
|
const iname = generateGenericName(params);
|
||||||
|
|
||||||
|
type.id = this.id.concat(name, iname);
|
||||||
|
|
||||||
|
template.instances.push({params, type});
|
||||||
}
|
}
|
||||||
|
|
||||||
addDefinition(schema: Schema, declared: boolean) {
|
addDefinition(name: string, type: Type, declared: boolean) {
|
||||||
const decl = this._entries.get(schema.name);
|
const decl = this._entries.get(name);
|
||||||
|
|
||||||
if (declared) {
|
if (declared) {
|
||||||
invariant(decl);
|
invariant(decl);
|
||||||
invariant(decl.type === 'declaration');
|
invariant(decl.kind === 'declaration');
|
||||||
} else {
|
} else {
|
||||||
invariant(!decl);
|
invariant(!decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._entries.set(schema.name, {
|
type.id = this.id.concat(name);
|
||||||
type: 'definition',
|
|
||||||
schema,
|
this._entries.set(name, {
|
||||||
|
kind: 'definition',
|
||||||
|
type,
|
||||||
scope: this,
|
scope: this,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -95,7 +94,7 @@ export default class Scope {
|
||||||
invariant(!this._entries.has(info.local));
|
invariant(!this._entries.has(info.local));
|
||||||
|
|
||||||
this._entries.set(info.local, {
|
this._entries.set(info.local, {
|
||||||
type: 'external',
|
kind: 'external',
|
||||||
info,
|
info,
|
||||||
scope: this,
|
scope: this,
|
||||||
});
|
});
|
||||||
|
@ -116,14 +115,14 @@ export default class Scope {
|
||||||
query(name: string, params: (?Type)[]): Query {
|
query(name: string, params: (?Type)[]): Query {
|
||||||
const entry = this._entries.get(name);
|
const entry = this._entries.get(name);
|
||||||
|
|
||||||
if (entry && entry.type === 'template') {
|
if (entry && entry.kind === 'template') {
|
||||||
const augmented = entry.params.map((p, i) => params[i] === undefined ? p.default : params[i]);
|
const augmented = entry.params.map((p, i) => params[i] === undefined ? p.value : params[i]);
|
||||||
const schema = findInstance(entry, augmented);
|
const type = findInstance(entry, augmented);
|
||||||
|
|
||||||
if (schema) {
|
if (type) {
|
||||||
return {
|
return {
|
||||||
type: 'definition',
|
kind: 'definition',
|
||||||
schema,
|
type,
|
||||||
scope: entry.scope,
|
scope: entry.scope,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -138,20 +137,46 @@ export default class Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'unknown',
|
kind: 'unknown',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findInstance(template: Template, queried: (?Type)[]): ?Schema {
|
function findInstance(template: Template, queried: (?Type)[]): ?Type {
|
||||||
for (const {schema, params} of template.instances) {
|
for (const {type, params} of template.instances) {
|
||||||
// TODO: compare complex structures.
|
// TODO: compare complex structures.
|
||||||
const same = params.every((p, i) => p === queried[i]);
|
const same = params.every((p, i) => p === queried[i]);
|
||||||
|
|
||||||
if (same) {
|
if (same) {
|
||||||
return schema;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateGenericName(params: (?Type)[]): TypeId {
|
||||||
|
return wu(params)
|
||||||
|
.map(type => {
|
||||||
|
invariant(type);
|
||||||
|
return getTypeName(type);
|
||||||
|
})
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTypeName(type: Type): string {
|
||||||
|
switch (type.kind) {
|
||||||
|
case 'reference':
|
||||||
|
const name = last(type.to);
|
||||||
|
invariant(name != null);
|
||||||
|
|
||||||
|
return name;
|
||||||
|
case 'number':
|
||||||
|
return type.repr;
|
||||||
|
case 'string':
|
||||||
|
case 'boolean':
|
||||||
|
return type.kind;
|
||||||
|
default:
|
||||||
|
invariant(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
export type Type =
|
||||||
|
| RecordType
|
||||||
|
| ArrayType
|
||||||
|
| TupleType
|
||||||
|
| MapType
|
||||||
|
| UnionType
|
||||||
|
| IntersectionType
|
||||||
|
| MaybeType
|
||||||
|
| NumberType
|
||||||
|
| StringType
|
||||||
|
| BooleanType
|
||||||
|
| LiteralType
|
||||||
|
| ReferenceType;
|
||||||
|
|
||||||
|
export type TypeId = string[];
|
||||||
|
|
||||||
|
export type BaseType = {
|
||||||
|
id?: TypeId,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type RecordType = BaseType & {
|
||||||
|
kind: 'record',
|
||||||
|
fields: Field[],
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Field = {
|
||||||
|
name: string,
|
||||||
|
value: Type,
|
||||||
|
required: boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ArrayType = BaseType & {
|
||||||
|
kind: 'array',
|
||||||
|
items: Type,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TupleType = BaseType & {
|
||||||
|
kind: 'tuple',
|
||||||
|
items: Type[],
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MapType = BaseType & {
|
||||||
|
kind: 'map',
|
||||||
|
keys: Type,
|
||||||
|
values: Type,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UnionType = BaseType & {
|
||||||
|
kind: 'union',
|
||||||
|
variants: Type[],
|
||||||
|
};
|
||||||
|
|
||||||
|
export type IntersectionType = BaseType & {
|
||||||
|
kind: 'intersection',
|
||||||
|
parts: Type[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MaybeType = BaseType & {
|
||||||
|
kind: 'maybe',
|
||||||
|
value: Type,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type NumberType = BaseType & {
|
||||||
|
kind: 'number',
|
||||||
|
repr: 'i32' | 'i64' | 'u32' | 'u64' | 'f32' | 'f64',
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StringType = BaseType & {
|
||||||
|
kind: 'string',
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BooleanType = BaseType & {
|
||||||
|
kind: 'boolean',
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LiteralType = BaseType & {
|
||||||
|
kind: 'literal',
|
||||||
|
value: string | number | boolean | null | void,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReferenceType = BaseType & {
|
||||||
|
kind: 'reference',
|
||||||
|
to: TypeId,
|
||||||
|
};
|
61
src/utils.js
61
src/utils.js
|
@ -4,67 +4,6 @@ import * as assert from 'assert';
|
||||||
// @see flow#112.
|
// @see flow#112.
|
||||||
export const invariant = assert.ok;
|
export const invariant = assert.ok;
|
||||||
|
|
||||||
export function partition<T>(iter: Iterable<T>, predicate: T => boolean): [T[], T[]] {
|
|
||||||
const left = [];
|
|
||||||
const right = [];
|
|
||||||
|
|
||||||
for (const item of iter) {
|
|
||||||
(predicate(item) ? left : right).push(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [left, right];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function map<T, R>(iter: Iterable<T>, mapper: T => R): R[] {
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
for (const item of iter) {
|
|
||||||
result.push(mapper(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function filter<T>(iter: Iterable<T>, predicate: T => boolean): T[] {
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
for (const item of iter) {
|
|
||||||
if (predicate(item)) {
|
|
||||||
result.push(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function filterMap<T, R>(iter: Iterable<T>, mapper: T => ?R): R[] {
|
|
||||||
const result = [];
|
|
||||||
|
|
||||||
for (const item of iter) {
|
|
||||||
const it = mapper(item);
|
|
||||||
|
|
||||||
if (it != null) {
|
|
||||||
result.push(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function compact<T>(iter: Iterable<?T>): T[] {
|
|
||||||
// $FlowFixMe
|
|
||||||
return filter(iter, Boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
// $FlowFixMe
|
|
||||||
export function get<T: Object, K: $Keys<T>>(key: K): T => $ElementType<T, K> {
|
|
||||||
return obj => obj[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function compose<X, Y, Z>(a: X => Y, b: Y => Z): X => Z {
|
|
||||||
return x => b(a(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function last<T>(list: T[]): T | void {
|
export function last<T>(list: T[]): T | void {
|
||||||
return list.length > 0 ? list[list.length - 1] : undefined;
|
return list.length > 0 ? list[list.length - 1] : undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@ function run(title) {
|
||||||
expected = JSON.parse(fs.readFileSync(title + '.json', 'utf8'));
|
expected = JSON.parse(fs.readFileSync(title + '.json', 'utf8'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should provide expected schemas', () => {
|
it('should provide expected types', () => {
|
||||||
assert.deepEqual(actual.schemas, expected.schemas);
|
assert.deepEqual(actual.types, expected.types);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
type Type = {
|
type Type = {
|
||||||
a: number[],
|
a: string[],
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Interface {
|
interface Interface {
|
||||||
a: number[];
|
a: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
a: number[];
|
a: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Type, Interface, Class};
|
export {Type, Interface, Class};
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["arrays", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "arrays",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": {"type": "array", "items": "double"}
|
"value": {"kind": "array", "items": {"kind": "string"}},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["arrays", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "arrays",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": {"type": "array", "items": "double"}
|
"value": {"kind": "array", "items": {"kind": "string"}},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["arrays", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "arrays",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": {"type": "array", "items": "double"}
|
"value": {"kind": "array", "items": {"kind": "string"}},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"id": ["disorder", "Z"],
|
||||||
"name": "Z",
|
"kind": "string"
|
||||||
"namespace": "disorder"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["disorder", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "disorder",
|
"fields": [
|
||||||
"fields": [{"name": "z", "type": "Z"}]
|
{"name": "z", "value": {"kind": "reference", "to": ["disorder", "Z"]}, "required": true}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["disorder", "X"],
|
||||||
"name": "X",
|
"kind": "record",
|
||||||
"namespace": "disorder",
|
"fields": [
|
||||||
"fields": [{"name": "y", "type": "Y"}]
|
{"name": "y", "value": {"kind": "reference", "to": ["disorder", "Y"]}, "required": true}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"schemas": []
|
"types": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,48 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["enums", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "enums",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": {"type": "enum", "symbols": ["one", "two"]}
|
"value": {
|
||||||
|
"kind": "union",
|
||||||
|
"variants": [
|
||||||
|
{"kind": "literal", "value": "one"},
|
||||||
|
{"kind": "literal", "value": "two"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["enums", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "enums",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": {"type": "enum", "symbols": ["one", "two"]}
|
"value": {
|
||||||
|
"kind": "union",
|
||||||
|
"variants": [
|
||||||
|
{"kind": "literal", "value": "one"},
|
||||||
|
{"kind": "literal", "value": "two"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["enums", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "enums",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": {"type": "enum", "symbols": ["one", "two"]}
|
"value": {
|
||||||
|
"kind": "union",
|
||||||
|
"variants": [
|
||||||
|
{"kind": "literal", "value": "one"},
|
||||||
|
{"kind": "literal", "value": "two"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,73 +1,63 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "first", "A"],
|
||||||
"name": "A",
|
"kind": "record",
|
||||||
"namespace": "externals.first",
|
"fields": [{"name": "a", "value": {"kind": "boolean"}, "required": true}]
|
||||||
"fields": [{"name": "a", "type": "boolean"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "first", "B"],
|
||||||
"name": "B",
|
"kind": "record",
|
||||||
"namespace": "externals.first",
|
"fields": [{"name": "b", "value": {"kind": "string"}, "required": true}]
|
||||||
"fields": [{"name": "b", "type": "string"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "first", "CC"],
|
||||||
"name": "CC",
|
"kind": "record",
|
||||||
"namespace": "externals.first",
|
"fields": [{"name": "c", "value": {"kind": "number", "repr": "f64"}, "required": true}]
|
||||||
"fields": [{"name": "c", "type": "double"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "first", "D"],
|
||||||
"name": "D",
|
"kind": "record",
|
||||||
"namespace": "externals.first",
|
"fields": [{"name": "d", "value": {"kind": "number", "repr": "f64"}, "required": true}]
|
||||||
"fields": [{"name": "d", "type": "double"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "X"],
|
||||||
"name": "X",
|
"kind": "record",
|
||||||
"namespace": "externals",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "externals.first.A"},
|
{"name": "a", "value": {"kind": "reference", "to": ["externals", "first", "A"]}, "required": true},
|
||||||
{"name": "b", "type": "externals.first.B"},
|
{"name": "b", "value": {"kind": "reference", "to": ["externals", "first", "B"]}, "required": true},
|
||||||
{"name": "c", "type": "externals.first.CC"},
|
{"name": "c", "value": {"kind": "reference", "to": ["externals", "first", "CC"]}, "required": true},
|
||||||
{"name": "d", "type": "externals.first.D"}
|
{"name": "d", "value": {"kind": "reference", "to": ["externals", "first", "D"]}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "second", "N"],
|
||||||
"name": "N",
|
"kind": "record",
|
||||||
"namespace": "externals.second",
|
"fields": [{"name": "n", "value": {"kind": "boolean"}, "required": true}]
|
||||||
"fields": [{"name": "n", "type": "boolean"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "second", "M"],
|
||||||
"name": "M",
|
"kind": "record",
|
||||||
"namespace": "externals.second",
|
"fields": [{"name": "m", "value": {"kind": "string"}, "required": true}]
|
||||||
"fields": [{"name": "m", "type": "string"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "second", "KK"],
|
||||||
"name": "KK",
|
"kind": "record",
|
||||||
"namespace": "externals.second",
|
"fields": [{"name": "k", "value": {"kind": "number", "repr": "f64"}, "required": true}]
|
||||||
"fields": [{"name": "k", "type": "double"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "second", "P"],
|
||||||
"name": "P",
|
"kind": "record",
|
||||||
"namespace": "externals.second",
|
"fields": [{"name": "p", "value": {"kind": "number", "repr": "f64"}, "required": true}]
|
||||||
"fields": [{"name": "p", "type": "double"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["externals", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "externals",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "n", "type": "externals.second.N"},
|
{"name": "n", "value": {"kind": "reference", "to": ["externals", "second", "N"]}, "required": true},
|
||||||
{"name": "m", "type": "externals.second.M"},
|
{"name": "m", "value": {"kind": "reference", "to": ["externals", "second", "M"]}, "required": true},
|
||||||
{"name": "k", "type": "externals.second.KK"},
|
{"name": "k", "value": {"kind": "reference", "to": ["externals", "second", "KK"]}, "required": true},
|
||||||
{"name": "p", "type": "externals.second.P"}
|
{"name": "p", "value": {"kind": "reference", "to": ["externals", "second", "P"]}, "required": true}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,7 +4,7 @@ type A<T, K> = {
|
||||||
};
|
};
|
||||||
|
|
||||||
type X = {
|
type X = {
|
||||||
a: A<string, number>,
|
a: A<string, boolean>,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {X};
|
export {X};
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["generics", "A", "string", "boolean"],
|
||||||
"name": "A__string_double",
|
"kind": "record",
|
||||||
"namespace": "generics",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "t", "type": "string"},
|
{"name": "t", "value": {"kind": "string"}, "required": true},
|
||||||
{"name": "k", "type": "double"}
|
{"name": "k", "value": {"kind": "boolean"}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["generics", "X"],
|
||||||
"name": "X",
|
"kind": "record",
|
||||||
"namespace": "generics",
|
"fields": [{
|
||||||
"fields": [{"name": "a", "type": "A__string_double"}]
|
"name": "a",
|
||||||
|
"value": {"kind": "reference", "to": ["generics", "A", "string", "boolean"]},
|
||||||
|
"required": true
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,53 +1,57 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["inheritance", "A"],
|
||||||
"name": "A",
|
"kind": "record",
|
||||||
"namespace": "inheritance",
|
"fields": [{"name": "a", "value": {"kind": "number", "repr": "f64"}, "required": true}]
|
||||||
"fields": [{"name": "a", "type": "double"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["inheritance", "B"],
|
||||||
"name": "B",
|
"kind": "intersection",
|
||||||
"namespace": "inheritance",
|
"parts": [
|
||||||
"fields": [
|
{"kind": "reference", "to": ["inheritance", "A"]},
|
||||||
{"name": "a", "type": "double"},
|
{
|
||||||
{"name": "b", "type": "string"}
|
"kind": "record",
|
||||||
|
"fields": [{"name": "b", "value": {"kind": "string"}, "required": true}]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["inheritance", "C"],
|
||||||
"name": "C",
|
"kind": "intersection",
|
||||||
"namespace": "inheritance",
|
"parts": [
|
||||||
"fields": [
|
{"kind": "reference", "to": ["inheritance", "B"]},
|
||||||
{"name": "a", "type": "double"},
|
{
|
||||||
{"name": "b", "type": "string"},
|
"kind": "record",
|
||||||
{"name": "c", "type": "boolean"}
|
"fields": [{"name": "c", "value": {"kind": "boolean"}, "required": true}]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["inheritance", "X"],
|
||||||
"name": "X",
|
"kind": "record",
|
||||||
"namespace": "inheritance",
|
"fields": [{"name": "x", "value": {"kind": "number", "repr": "f64"}, "required": true}]
|
||||||
"fields": [{"name": "x", "type": "double"}]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["inheritance", "Y"],
|
||||||
"name": "Y",
|
"kind": "intersection",
|
||||||
"namespace": "inheritance",
|
"parts": [
|
||||||
"fields": [
|
{"kind": "reference", "to": ["inheritance", "X"]},
|
||||||
{"name": "x", "type": "double"},
|
{
|
||||||
{"name": "y", "type": "string"}
|
"kind": "record",
|
||||||
|
"fields": [{"name": "y", "value": {"kind": "string"}, "required": true}]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["inheritance", "Z"],
|
||||||
"name": "Z",
|
"kind": "intersection",
|
||||||
"namespace": "inheritance",
|
"parts": [
|
||||||
"fields": [
|
{"kind": "reference", "to": ["inheritance", "Y"]},
|
||||||
{"name": "x", "type": "double"},
|
{
|
||||||
{"name": "y", "type": "string"},
|
"kind": "record",
|
||||||
{"name": "z", "type": "boolean"}
|
"fields": [{"name": "z", "value": {"kind": "boolean"}, "required": true}]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,66 +1,64 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["intersections", "A"],
|
||||||
"name": "A",
|
"kind": "record",
|
||||||
"namespace": "intersections",
|
|
||||||
"fields": [{"name": "a", "type": "double"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "record",
|
|
||||||
"name": "B",
|
|
||||||
"namespace": "intersections",
|
|
||||||
"fields": [{"name": "b", "type": "string"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "record",
|
|
||||||
"name": "X",
|
|
||||||
"namespace": "intersections",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "double"},
|
{"name": "a", "value": {"kind": "number", "repr": "f64"}, "required": true}
|
||||||
{"name": "b", "type": "string"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["intersections", "B"],
|
||||||
"name": "C",
|
"kind": "record",
|
||||||
"namespace": "intersections",
|
|
||||||
"fields": [{"name": "c", "type": "boolean"}]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "record",
|
|
||||||
"name": "_A_B_C",
|
|
||||||
"namespace": "intersections",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "double"},
|
{"name": "b", "value": {"kind": "string"}, "required": true}
|
||||||
{"name": "b", "type": "string"},
|
|
||||||
{"name": "c", "type": "boolean"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["intersections", "X"],
|
||||||
"name": "Y",
|
"kind": "intersection",
|
||||||
"namespace": "intersections",
|
"parts": [
|
||||||
"fields": [
|
{"kind": "reference", "to": ["intersections", "A"]},
|
||||||
{"name": "y", "type": "_A_B_C"}
|
{"kind": "reference", "to": ["intersections", "B"]}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["intersections", "C"],
|
||||||
"name": "_A_C",
|
"kind": "record",
|
||||||
"namespace": "intersections",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "double"},
|
{"name": "c", "value": {"kind": "boolean"}, "required": true}
|
||||||
{"name": "c", "type": "boolean"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["intersections", "Y"],
|
||||||
"name": "Z",
|
"kind": "record",
|
||||||
"namespace": "intersections",
|
"fields": [{
|
||||||
"fields": [
|
"name": "y",
|
||||||
{"name": "z", "type": "_A_C"}
|
"value": {
|
||||||
]
|
"kind": "intersection",
|
||||||
|
"parts": [
|
||||||
|
{"kind": "reference", "to": ["intersections", "A"]},
|
||||||
|
{"kind": "reference", "to": ["intersections", "B"]},
|
||||||
|
{"kind": "reference", "to": ["intersections", "C"]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": ["intersections", "Z"],
|
||||||
|
"kind": "record",
|
||||||
|
"fields": [{
|
||||||
|
"name": "z",
|
||||||
|
"value": {
|
||||||
|
"kind": "intersection",
|
||||||
|
"parts": [
|
||||||
|
{"kind": "reference", "to": ["intersections", "A"]},
|
||||||
|
{"kind": "reference", "to": ["intersections", "C"]}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
type Type = {
|
type Type = {
|
||||||
[string]: number,
|
[string]: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Interface {
|
interface Interface {
|
||||||
[string]: number;
|
[string]: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Type, Interface};
|
export {Type, Interface};
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "map",
|
"id": ["maps", "Type"],
|
||||||
"name": "Type",
|
"kind": "map",
|
||||||
"namespace": "maps",
|
"keys": {"kind": "string"},
|
||||||
"values": "double"
|
"values": {"kind": "boolean"}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "map",
|
"id": ["maps", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "map",
|
||||||
"namespace": "maps",
|
"keys": {"kind": "string"},
|
||||||
"values": "double"
|
"values": {"kind": "boolean"}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,34 @@
|
||||||
type Type = {
|
type Type = {
|
||||||
// $avro int
|
// @repr {i32}
|
||||||
a: number,
|
a: number,
|
||||||
/* $avro long */
|
/* @repr {i64} */
|
||||||
b: number,
|
b: number,
|
||||||
// $avro float
|
// @repr {f32}
|
||||||
c: number,
|
c: number,
|
||||||
// $avro double
|
// @repr {f64}
|
||||||
d: number,
|
d: number,
|
||||||
/* $avro fixed 10 */
|
|
||||||
e: Buffer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Interface {
|
interface Interface {
|
||||||
// $avro int
|
// @repr {i32}
|
||||||
a: number;
|
a: number;
|
||||||
/* $avro long */
|
/* @repr {i64} */
|
||||||
b: number;
|
b: number;
|
||||||
// $avro float
|
// @repr {f32}
|
||||||
c: number;
|
c: number;
|
||||||
// $avro double
|
// @repr {f64}
|
||||||
d: number;
|
d: number;
|
||||||
/* $avro fixed 10 */
|
|
||||||
e: Buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
// $avro int
|
// @repr {i32}
|
||||||
a: number;
|
a: number;
|
||||||
/* $avro long */
|
/* @repr {i64} */
|
||||||
b: number;
|
b: number;
|
||||||
// $avro float
|
// @repr {f32}
|
||||||
c: number;
|
c: number;
|
||||||
// $avro double
|
// @repr {f64}
|
||||||
d: number;
|
d: number;
|
||||||
/* $avro fixed 10 */
|
|
||||||
e: Buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Type, Interface, Class};
|
export {Type, Interface, Class};
|
||||||
|
|
|
@ -1,39 +1,33 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["pragmas", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "pragmas",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "int"},
|
{"name": "a", "value": {"kind": "number", "repr": "i32"}, "required": true},
|
||||||
{"name": "b", "type": "long"},
|
{"name": "b", "value": {"kind": "number", "repr": "i64"}, "required": true},
|
||||||
{"name": "c", "type": "float"},
|
{"name": "c", "value": {"kind": "number", "repr": "f32"}, "required": true},
|
||||||
{"name": "d", "type": "double"},
|
{"name": "d", "value": {"kind": "number", "repr": "f64"}, "required": true}
|
||||||
{"name": "e", "type": {"type": "fixed", "size": 10}}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["pragmas", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "pragmas",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "int"},
|
{"name": "a", "value": {"kind": "number", "repr": "i32"}, "required": true},
|
||||||
{"name": "b", "type": "long"},
|
{"name": "b", "value": {"kind": "number", "repr": "i64"}, "required": true},
|
||||||
{"name": "c", "type": "float"},
|
{"name": "c", "value": {"kind": "number", "repr": "f32"}, "required": true},
|
||||||
{"name": "d", "type": "double"},
|
{"name": "d", "value": {"kind": "number", "repr": "f64"}, "required": true}
|
||||||
{"name": "e", "type": {"type": "fixed", "size": 10}}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["pragmas", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "pragmas",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "int"},
|
{"name": "a", "value": {"kind": "number", "repr": "i32"}, "required": true},
|
||||||
{"name": "b", "type": "long"},
|
{"name": "b", "value": {"kind": "number", "repr": "i64"}, "required": true},
|
||||||
{"name": "c", "type": "float"},
|
{"name": "c", "value": {"kind": "number", "repr": "f32"}, "required": true},
|
||||||
{"name": "d", "type": "double"},
|
{"name": "d", "value": {"kind": "number", "repr": "f64"}, "required": true}
|
||||||
{"name": "e", "type": {"type": "fixed", "size": 10}}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,6 @@ type Type = {
|
||||||
b: number,
|
b: number,
|
||||||
c: boolean,
|
c: boolean,
|
||||||
d: null,
|
d: null,
|
||||||
e: Buffer,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Interface {
|
interface Interface {
|
||||||
|
@ -11,7 +10,6 @@ interface Interface {
|
||||||
b: number;
|
b: number;
|
||||||
c: boolean;
|
c: boolean;
|
||||||
d: null;
|
d: null;
|
||||||
e: Buffer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
|
@ -19,7 +17,6 @@ class Class {
|
||||||
b: number;
|
b: number;
|
||||||
c: boolean;
|
c: boolean;
|
||||||
d: null;
|
d: null;
|
||||||
e: Buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Type, Interface, Class};
|
export {Type, Interface, Class};
|
||||||
|
|
|
@ -1,39 +1,33 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["primitives", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "primitives",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "string"},
|
{"name": "a", "value": {"kind": "string"}, "required": true},
|
||||||
{"name": "b", "type": "double"},
|
{"name": "b", "value": {"kind": "number", "repr": "f64"}, "required": true},
|
||||||
{"name": "c", "type": "boolean"},
|
{"name": "c", "value": {"kind": "boolean"}, "required": true},
|
||||||
{"name": "d", "type": "null"},
|
{"name": "d", "value": {"kind": "literal", "value": null}, "required": true}
|
||||||
{"name": "e", "type": "bytes"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["primitives", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "primitives",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "string"},
|
{"name": "a", "value": {"kind": "string"}, "required": true},
|
||||||
{"name": "b", "type": "double"},
|
{"name": "b", "value": {"kind": "number", "repr": "f64"}, "required": true},
|
||||||
{"name": "c", "type": "boolean"},
|
{"name": "c", "value": {"kind": "boolean"}, "required": true},
|
||||||
{"name": "d", "type": "null"},
|
{"name": "d", "value": {"kind": "literal", "value": null}, "required": true}
|
||||||
{"name": "e", "type": "bytes"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["primitives", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "primitives",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "string"},
|
{"name": "a", "value": {"kind": "string"}, "required": true},
|
||||||
{"name": "b", "type": "double"},
|
{"name": "b", "value": {"kind": "number", "repr": "f64"}, "required": true},
|
||||||
{"name": "c", "type": "boolean"},
|
{"name": "c", "value": {"kind": "boolean"}, "required": true},
|
||||||
{"name": "d", "type": "null"},
|
{"name": "d", "value": {"kind": "literal", "value": null}, "required": true}
|
||||||
{"name": "e", "type": "bytes"}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,35 +1,55 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"id": ["references", "A"],
|
||||||
"name": "A",
|
"kind": "string"
|
||||||
"namespace": "references"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["references", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "references",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "A"},
|
{
|
||||||
{"name": "b", "type": {"type": "array", "items": "A"}}
|
"name": "a",
|
||||||
|
"value": {"kind": "reference", "to": ["references", "A"]},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"value": {"kind": "array", "items": {"kind": "reference", "to": ["references", "A"]}},
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["references", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "references",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "A"},
|
{
|
||||||
{"name": "b", "type": {"type": "array", "items": "A"}}
|
"name": "a",
|
||||||
|
"value": {"kind": "reference", "to": ["references", "A"]},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"value": {"kind": "array", "items": {"kind": "reference", "to": ["references", "A"]}},
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["references", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "references",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "A"},
|
{
|
||||||
{"name": "b", "type": {"type": "array", "items": "A"}}
|
"name": "a",
|
||||||
|
"value": {"kind": "reference", "to": ["references", "A"]},
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "b",
|
||||||
|
"value": {"kind": "array", "items": {"kind": "reference", "to": ["references", "A"]}},
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,73 +1,68 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "boolean",
|
"id": ["scopes", "2", "X"],
|
||||||
"name": "X",
|
"kind": "boolean"
|
||||||
"namespace": "scopes._2"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"id": ["scopes", "1", "Z"],
|
||||||
"name": "Z",
|
"kind": "string"
|
||||||
"namespace": "scopes._1"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["scopes", "2", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "scopes._2",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "x", "type": "X"},
|
{"name": "x", "value": {"kind": "reference", "to": ["scopes", "2", "X"]}, "required": true},
|
||||||
{"name": "z", "type": "scopes._1.Z"}
|
{"name": "z", "value": {"kind": "reference", "to": ["scopes", "1", "Z"]}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "double",
|
"id": ["scopes", "3", "X"],
|
||||||
"name": "X",
|
"kind": "number",
|
||||||
"namespace": "scopes._3"
|
"repr": "f64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["scopes", "3", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "scopes._3",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "x", "type": "X"},
|
{"name": "x", "value": {"kind": "reference", "to": ["scopes", "3", "X"]}, "required": true},
|
||||||
{"name": "z", "type": "scopes._1.Z"}
|
{"name": "z", "value": {"kind": "reference", "to": ["scopes", "1", "Z"]}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"id": ["scopes", "4", "X"],
|
||||||
"name": "X",
|
"kind": "string"
|
||||||
"namespace": "scopes._4"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["scopes", "4", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "scopes._4",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "x", "type": "X"},
|
{"name": "x", "value": {"kind": "reference", "to": ["scopes", "4", "X"]}, "required": true},
|
||||||
{"name": "z", "type": "scopes._1.Z"}
|
{"name": "z", "value": {"kind": "reference", "to": ["scopes", "1", "Z"]}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "double",
|
"id": ["scopes", "1", "X"],
|
||||||
"name": "X",
|
"kind": "number",
|
||||||
"namespace": "scopes._1"
|
"repr": "f64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["scopes", "1", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "scopes._1",
|
"fields": [
|
||||||
"fields": [{"name": "x", "type": "X"}]
|
{"name": "x", "value": {"kind": "reference", "to": ["scopes", "1", "X"]}, "required": true}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"id": ["scopes", "X"],
|
||||||
"name": "X",
|
"kind": "string"
|
||||||
"namespace": "scopes"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["scopes", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "scopes",
|
"fields": [
|
||||||
"fields": [{"name": "x", "type": "X"}]
|
{"name": "x", "value": {"kind": "reference", "to": ["scopes", "X"]}, "required": true}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,30 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["shadowing", "1", "Buffer"],
|
||||||
"name": "Buffer",
|
"kind": "record",
|
||||||
"namespace": "shadowing._1",
|
|
||||||
"fields": []
|
"fields": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["shadowing", "1", "Y"],
|
||||||
"name": "Y",
|
"kind": "record",
|
||||||
"namespace": "shadowing._1",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "y", "type": "Buffer"}
|
{
|
||||||
|
"name": "y",
|
||||||
|
"value": {"kind": "reference", "to": ["shadowing", "1", "Buffer"]},
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["shadowing", "X"],
|
||||||
"name": "X",
|
"kind": "record",
|
||||||
"namespace": "shadowing",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "x", "type": "bytes"}
|
{
|
||||||
|
"name": "x",
|
||||||
|
"value": {"kind": "reference", "to": ["Buffer"]},
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,7 @@ type Type = {
|
||||||
|
|
||||||
foo(): void,
|
foo(): void,
|
||||||
|
|
||||||
b: number,
|
b: boolean,
|
||||||
|
|
||||||
bar: () => void,
|
bar: () => void,
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,7 @@ interface Interface {
|
||||||
|
|
||||||
foo(): void;
|
foo(): void;
|
||||||
|
|
||||||
b: number;
|
b: boolean;
|
||||||
|
|
||||||
bar: () => void;
|
bar: () => void;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class Class {
|
||||||
get bar() {}
|
get bar() {}
|
||||||
set bar(a) {}
|
set bar(a) {}
|
||||||
|
|
||||||
b: number;
|
b: boolean;
|
||||||
|
|
||||||
baz: () => void;
|
baz: () => void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,27 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["skipFunctions", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "skipFunctions",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "string"},
|
{"name": "a", "value": {"kind": "string"}, "required": true},
|
||||||
{"name": "b", "type": "double"}
|
{"name": "b", "value": {"kind": "boolean"}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["skipFunctions", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "skipFunctions",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "string"},
|
{"name": "a", "value": {"kind": "string"}, "required": true},
|
||||||
{"name": "b", "type": "double"}
|
{"name": "b", "value": {"kind": "boolean"}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["skipFunctions", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "skipFunctions",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": "string"},
|
{"name": "a", "value": {"kind": "string"}, "required": true},
|
||||||
{"name": "b", "type": "double"}
|
{"name": "b", "value": {"kind": "boolean"}, "required": true}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["typeInMethod", "Test"],
|
||||||
"name": "Test",
|
"kind": "record",
|
||||||
"namespace": "typeInMethod",
|
|
||||||
"fields": []
|
"fields": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["typeInMethod", "1", "X"],
|
||||||
"name": "X",
|
"kind": "record",
|
||||||
"namespace": "typeInMethod._1",
|
"fields": [{
|
||||||
"fields": [{"name": "t", "type": "typeInMethod.Test"}]
|
"name": "t",
|
||||||
|
"value": {"kind": "reference", "to": ["typeInMethod", "Test"]},
|
||||||
|
"required": true
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
type Type = {
|
type Type = {
|
||||||
a: string | number,
|
a: string | boolean,
|
||||||
b: ?string,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Interface {
|
interface Interface {
|
||||||
a: string | number;
|
a: string | boolean | number;
|
||||||
b: ?string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
a: string | number;
|
a: string | boolean;
|
||||||
b: ?string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Type, Interface, Class};
|
export {Type, Interface, Class};
|
||||||
|
|
|
@ -1,47 +1,44 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["unions", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "unions",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": ["string", "double"]
|
"value": {
|
||||||
},
|
"kind": "union",
|
||||||
{
|
"variants": [{"kind": "string"}, {"kind": "boolean"}]
|
||||||
"name": "b",
|
},
|
||||||
"type": ["null", "string"]
|
"required": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["unions", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "unions",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": ["string", "double"]
|
"value": {
|
||||||
},
|
"kind": "union",
|
||||||
{
|
"variants": [{"kind": "string"}, {"kind": "boolean"}, {"kind": "number", "repr": "f64"}]
|
||||||
"name": "b",
|
},
|
||||||
"type": ["null", "string"]
|
"required": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["unions", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "unions",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": ["string", "double"]
|
"value": {
|
||||||
},
|
"kind": "union",
|
||||||
{
|
"variants": [{"kind": "string"}, {"kind": "boolean"}]
|
||||||
"name": "b",
|
},
|
||||||
"type": ["null", "string"]
|
"required": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
type Type = {
|
type Type = {
|
||||||
a: 'one' | 'two' | number,
|
a: 'one' | 'two' | string,
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Interface {
|
interface Interface {
|
||||||
a: 'one' | 'two' | number;
|
a: 'one' | 'two' | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Class {
|
class Class {
|
||||||
a: 'one' | 'two' | number;
|
a: 'one' | 'two' | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {Type, Interface, Class};
|
export {Type, Interface, Class};
|
||||||
|
|
|
@ -1,39 +1,51 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["unionsAndEnums", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "unionsAndEnums",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": [
|
"value": {
|
||||||
"double",
|
"kind": "union",
|
||||||
{"type": "enum", "symbols": ["one", "two"]}
|
"variants": [
|
||||||
]
|
{"kind": "literal", "value": "one"},
|
||||||
|
{"kind": "literal", "value": "two"},
|
||||||
|
{"kind": "string"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["unionsAndEnums", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "unionsAndEnums",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": [
|
"value": {
|
||||||
"double",
|
"kind": "union",
|
||||||
{"type": "enum", "symbols": ["one", "two"]}
|
"variants": [
|
||||||
]
|
{"kind": "literal", "value": "one"},
|
||||||
|
{"kind": "literal", "value": "two"},
|
||||||
|
{"kind": "string"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["unionsAndEnums", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "unionsAndEnums",
|
|
||||||
"fields": [{
|
"fields": [{
|
||||||
"name": "a",
|
"name": "a",
|
||||||
"type": [
|
"value": {
|
||||||
"double",
|
"kind": "union",
|
||||||
{"type": "enum", "symbols": ["one", "two"]}
|
"variants": [
|
||||||
]
|
{"kind": "literal", "value": "one"},
|
||||||
|
{"kind": "literal", "value": "two"},
|
||||||
|
{"kind": "string"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"required": true
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"schemas": []
|
"types": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,24 @@
|
||||||
{
|
{
|
||||||
"schemas": [
|
"types": [
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["valueAsType", "Type"],
|
||||||
"name": "Type",
|
"kind": "record",
|
||||||
"namespace": "valueAsType",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": {"type": "enum", "symbols": ["one"]}}
|
{"name": "a", "value": {"kind": "literal", "value": "one"}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["valueAsType", "Interface"],
|
||||||
"name": "Interface",
|
"kind": "record",
|
||||||
"namespace": "valueAsType",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": {"type": "enum", "symbols": ["one"]}}
|
{"name": "a", "value": {"kind": "literal", "value": "one"}, "required": true}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "record",
|
"id": ["valueAsType", "Class"],
|
||||||
"name": "Class",
|
"kind": "record",
|
||||||
"namespace": "valueAsType",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{"name": "a", "type": {"type": "enum", "symbols": ["one"]}}
|
{"name": "a", "value": {"kind": "literal", "value": "one"}, "required": true}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue