Compare commits
14 Commits
Author | SHA1 | Date |
---|---|---|
Vitaliy Filippov | 6fe28de2dc | |
Vitaliy Filippov | e5afdbcb58 | |
Vitaliy Filippov | 1d0a098c39 | |
Vitaliy Filippov | ec681fe6fc | |
Vitaliy Filippov | 870756a440 | |
Vitaliy Filippov | 84aface8eb | |
Paul Loyd | e24a73b03b | |
Paul Loyd | 21851b0042 | |
Paul Loyd | a51d4bc5b3 | |
Paul Loyd | 06a15e2d67 | |
Paul Loyd | 921bdd04cb | |
Paul Loyd | cdc9304304 | |
Paul Loyd | 563789f555 | |
Paul Loyd | c9b24ee574 |
|
@ -9,13 +9,12 @@ declarations/
|
|||
|
||||
[lints]
|
||||
all=error
|
||||
unsafe-getters-setters=off
|
||||
|
||||
[options]
|
||||
all=true
|
||||
module.use_strict=true
|
||||
munge_underscores=true
|
||||
include_warnings=true
|
||||
unsafe.enable_getters_and_setters=true
|
||||
suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe
|
||||
suppress_comment= \\(.\\|\n\\)*\\$FlowIssue
|
||||
suppress_type=$FlowFixMe
|
||||
|
|
|
@ -550,6 +550,7 @@ declare module '@babel/types' {
|
|||
|
||||
declare class BooleanLiteralTypeAnnotation extends Node {
|
||||
type: 'BooleanLiteralTypeAnnotation';
|
||||
value: boolean;
|
||||
}
|
||||
|
||||
declare class NullLiteralTypeAnnotation extends Node {
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
"@babel/preset-flow": "^7.0.0-beta.32",
|
||||
"@babel/register": "^7.0.0-beta.32",
|
||||
"ajv": "^5.5.1",
|
||||
"flow-bin": "^0.60.1",
|
||||
"flow-bin": "^0.77.0",
|
||||
"jasmine": "^2.8.0",
|
||||
"mocha": "^4.0.1",
|
||||
"nyc": "^11.3.0"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import * as yaml from 'yaml-js';
|
||||
import yargs from 'yargs';
|
||||
import stringifyJson from 'json-stringify-pretty-compact';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import wu from 'wu';
|
||||
import type {Node} from '@babel/types';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import wu from 'wu';
|
||||
|
||||
// @see flow#5376.
|
||||
|
@ -164,8 +166,8 @@ function extractCommonjsNamedExternals<+T: Node>(nodes: T[], path: string): Exte
|
|||
|
||||
function processExportNamedDeclaration(ctx: Context, node: ExportNamedDeclaration) {
|
||||
if (isDeclaration(node.declaration)) {
|
||||
node.declaration.leadingComments = node.leadingComments;
|
||||
const reference = processDeclaration(ctx, node.declaration);
|
||||
|
||||
ctx.provide(reference, reference);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// @flow
|
||||
|
||||
import wu from 'wu';
|
||||
|
||||
// @see flow#5376.
|
||||
import type {
|
||||
ArrayTypeAnnotation, ClassDeclaration, ClassProperty, Comment, FlowTypeAnnotation,
|
||||
Node, ArrayTypeAnnotation, ClassDeclaration, ClassProperty, Comment, FlowTypeAnnotation,
|
||||
GenericTypeAnnotation, InterfaceDeclaration, IntersectionTypeAnnotation, TypeAlias,
|
||||
UnionTypeAnnotation, NullableTypeAnnotation, ObjectTypeIndexer, ObjectTypeProperty,
|
||||
StringLiteralTypeAnnotation, ObjectTypeAnnotation, AnyTypeAnnotation, MixedTypeAnnotation,
|
||||
|
@ -10,7 +12,8 @@ import type {
|
|||
} from '@babel/types';
|
||||
|
||||
import {
|
||||
isIdentifier, isObjectTypeProperty, isStringLiteralTypeAnnotation, isClassProperty,
|
||||
isIdentifier, isStringLiteral, isObjectTypeProperty,
|
||||
isStringLiteralTypeAnnotation, isClassProperty,
|
||||
} from '@babel/types';
|
||||
|
||||
import Context from './context';
|
||||
|
@ -28,12 +31,28 @@ import {invariant} from '../utils';
|
|||
|
||||
function processTypeAlias(ctx: Context, node: TypeAlias | DeclareTypeAlias) {
|
||||
const {name} = node.id;
|
||||
const type = makeType(ctx, node.right);
|
||||
|
||||
// TODO: support function aliases.
|
||||
invariant(type);
|
||||
if (name != 'integer') {
|
||||
// Forward declaration for the recursive types
|
||||
ctx.define(name, t.createAny());
|
||||
|
||||
ctx.define(name, type);
|
||||
const type = makeType(ctx, node.right);
|
||||
addComment(node, type);
|
||||
|
||||
// TODO: support function aliases.
|
||||
invariant(type);
|
||||
|
||||
ctx.define(name, type);
|
||||
}
|
||||
}
|
||||
|
||||
function addComment(node: Node, type: Type) {
|
||||
if (node.leadingComments) {
|
||||
const cmt = node.leadingComments.map(c => c.value).join('\n').trim();
|
||||
if (cmt) {
|
||||
type.comment = cmt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: type params.
|
||||
|
@ -43,6 +62,7 @@ function processInterfaceDeclaration(
|
|||
) {
|
||||
const {name} = node.id;
|
||||
const type = makeType(ctx, node.body);
|
||||
addComment(node, type);
|
||||
|
||||
invariant(type);
|
||||
|
||||
|
@ -105,6 +125,8 @@ function makeType(ctx: Context, node: FlowTypeAnnotation): ?Type {
|
|||
return t.createLiteral(null);
|
||||
case 'BooleanTypeAnnotation':
|
||||
return t.createBoolean();
|
||||
case 'BooleanLiteralTypeAnnotation':
|
||||
return t.createLiteral(node.value);
|
||||
case 'NumberTypeAnnotation':
|
||||
return t.createNumber('f64');
|
||||
case 'StringTypeAnnotation':
|
||||
|
@ -132,7 +154,7 @@ function makeType(ctx: Context, node: FlowTypeAnnotation): ?Type {
|
|||
case 'MixedTypeAnnotation':
|
||||
return t.createMixed();
|
||||
case 'FunctionTypeAnnotation':
|
||||
return null;
|
||||
return t.createAny();
|
||||
default:
|
||||
invariant(false, `Unknown node: ${node.type}`);
|
||||
}
|
||||
|
@ -204,6 +226,7 @@ function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Fie
|
|||
invariant(value);
|
||||
|
||||
type = makeType(ctx, value);
|
||||
addComment(node, type);
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
|
@ -213,10 +236,12 @@ function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Fie
|
|||
// TODO: warning about computed properties.
|
||||
|
||||
invariant(isObjectTypeProperty(node) || !node.computed);
|
||||
invariant(isIdentifier(node.key));
|
||||
invariant(isIdentifier(node.key) || isStringLiteral(node.key));
|
||||
|
||||
const name = isIdentifier(node.key) ? node.key.name : node.key.value;
|
||||
|
||||
return {
|
||||
name: node.key.name,
|
||||
name,
|
||||
value: type,
|
||||
required: node.optional == null || !node.optional,
|
||||
};
|
||||
|
@ -225,12 +250,14 @@ function makeField(ctx: Context, node: ObjectTypeProperty | ClassProperty): ?Fie
|
|||
function makeMap(ctx: Context, node: ObjectTypeIndexer): ?MapType {
|
||||
const keys = makeType(ctx, node.key);
|
||||
const values = makeType(ctx, node.value);
|
||||
addComment(node, values);
|
||||
|
||||
return keys && values ? t.createMap(keys, values) : null;
|
||||
}
|
||||
|
||||
function makeArray(ctx: Context, node: ArrayTypeAnnotation): ?ArrayType {
|
||||
const items = makeType(ctx, node.elementType);
|
||||
addComment(node, items);
|
||||
|
||||
return items != null ? t.createArray(items) : null;
|
||||
}
|
||||
|
@ -271,6 +298,9 @@ function makeIntersection(ctx: Context, node: IntersectionTypeAnnotation): ?Type
|
|||
|
||||
function makeReference(ctx: Context, node: GenericTypeAnnotation): ?Type {
|
||||
const {name} = node.id;
|
||||
if (name == 'integer') {
|
||||
return t.createNumber('i64');
|
||||
}
|
||||
const params = node.typeParameters
|
||||
&& wu(node.typeParameters.params).map(n => makeType(ctx, n)).toArray();
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import wu from 'wu';
|
||||
|
||||
import {invariant} from '../utils';
|
||||
|
@ -196,6 +198,11 @@ function either(params: (?Type)[]): ?Type {
|
|||
: t.createUnion(variants);
|
||||
}
|
||||
|
||||
// $ FlowFixMe
|
||||
function fixMe(): ?Type {
|
||||
return t.createAny();
|
||||
}
|
||||
|
||||
export default {
|
||||
Object: object,
|
||||
Buffer: buffer,
|
||||
|
@ -212,4 +219,5 @@ export default {
|
|||
$Diff: diff,
|
||||
$All: all,
|
||||
$Either: either,
|
||||
$FlowFixMe: fixMe,
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as pathlib from 'path';
|
||||
import wu from 'wu';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import * as pathlib from 'path';
|
||||
import * as resolve from 'resolve';
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import {invariant} from '../utils';
|
||||
|
||||
import type {Type} from '../types';
|
||||
import * as t from '../types';
|
||||
import {createNumber, isRepr} from '../types';
|
||||
|
||||
export type Pragma =
|
||||
| TypePragma;
|
||||
| TypePragma
|
||||
;
|
||||
|
||||
export type TypePragma = {
|
||||
kind: 'type',
|
||||
|
@ -20,11 +23,11 @@ export function extractPragmas(text: string): Pragma[] {
|
|||
while ((match = PRAGMA_RE.exec(text))) {
|
||||
const repr = match[1];
|
||||
|
||||
invariant(['i32', 'i64', 'u32', 'u64', 'f32', 'f64'].includes(repr));
|
||||
invariant(isRepr(repr));
|
||||
|
||||
pragmas.push({
|
||||
kind: 'type',
|
||||
value: t.createNumber(repr),
|
||||
value: createNumber(repr),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import type {Node} from '@babel/types';
|
||||
|
||||
import type Scope from './scope';
|
||||
|
@ -9,7 +11,8 @@ export type Query =
|
|||
| Template
|
||||
| Definition
|
||||
| External
|
||||
| Special;
|
||||
| Special
|
||||
;
|
||||
|
||||
export type Unknown = {
|
||||
kind: 'unknown',
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import wu from 'wu';
|
||||
import type {Node} from '@babel/types';
|
||||
|
||||
|
@ -82,7 +84,7 @@ export default class Scope {
|
|||
|
||||
if (declared) {
|
||||
invariant(decl);
|
||||
invariant(decl.kind === 'declaration');
|
||||
invariant(decl.kind === 'declaration' || decl.kind === 'definition');
|
||||
} else {
|
||||
invariant(!decl);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import type {Node} from '@babel/types';
|
||||
import {VISITOR_KEYS} from '@babel/types';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import {invariant} from './utils';
|
||||
import type {TypeId, Type} from './types';
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import wu from 'wu';
|
||||
|
||||
import {invariant, collect, partition} from '../utils';
|
||||
|
@ -10,6 +12,7 @@ export type Schema = boolean | {
|
|||
id?: string,
|
||||
$ref?: string,
|
||||
$schema?: string,
|
||||
$comment?: string,
|
||||
title?: string,
|
||||
description?: string,
|
||||
default?: mixed,
|
||||
|
@ -43,6 +46,18 @@ export type Schema = boolean | {
|
|||
};
|
||||
|
||||
function convert(fund: Fund, type: ?Type): Schema {
|
||||
let schema = convertType(fund, type);
|
||||
if (type && type.comment) {
|
||||
if (schema === true) {
|
||||
schema = { $comment: type.comment };
|
||||
} else {
|
||||
schema.$comment = type.comment;
|
||||
}
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
function convertType(fund: Fund, type: ?Type): Schema {
|
||||
if (!type) {
|
||||
return {
|
||||
type: 'null',
|
||||
|
@ -88,13 +103,13 @@ function convert(fund: Fund, type: ?Type): Schema {
|
|||
};
|
||||
case 'union':
|
||||
const enumerate = wu(type.variants)
|
||||
.filter(variant => variant.kind === 'literal')
|
||||
.filter(variant => variant.kind === 'literal' && variant.value !== null)
|
||||
.map(literal => (literal: $FlowFixMe).value)
|
||||
.tap(value => invariant(value !== undefined))
|
||||
.toArray();
|
||||
|
||||
const schemas = wu(type.variants)
|
||||
.filter(variant => variant.kind !== 'literal')
|
||||
.filter(variant => variant.kind !== 'literal' || variant.value === null)
|
||||
.map(variant => convert(fund, variant))
|
||||
.toArray();
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import Parser from './parser';
|
||||
import Collector from './collector';
|
||||
import type {Type} from './types';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import * as babylon from 'babylon';
|
||||
import type {File} from '@babel/types';
|
||||
|
||||
|
|
38
src/types.js
38
src/types.js
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
export type Type =
|
||||
| RecordType
|
||||
| ArrayType
|
||||
|
@ -12,12 +14,14 @@ export type Type =
|
|||
| LiteralType
|
||||
| AnyType
|
||||
| MixedType
|
||||
| ReferenceType;
|
||||
| ReferenceType
|
||||
;
|
||||
|
||||
export type TypeId = string[];
|
||||
|
||||
export type BaseType = {
|
||||
id?: TypeId,
|
||||
comment?: string,
|
||||
};
|
||||
|
||||
export type RecordType = BaseType & {
|
||||
|
@ -64,9 +68,11 @@ export type MaybeType = BaseType & {
|
|||
|
||||
export type NumberType = BaseType & {
|
||||
kind: 'number',
|
||||
repr: 'i32' | 'i64' | 'u32' | 'u64' | 'f32' | 'f64',
|
||||
repr: Repr,
|
||||
};
|
||||
|
||||
export type Repr = 'i32' | 'i64' | 'u32' | 'u64' | 'f32' | 'f64';
|
||||
|
||||
export type StringType = BaseType & {
|
||||
kind: 'string',
|
||||
};
|
||||
|
@ -77,9 +83,11 @@ export type BooleanType = BaseType & {
|
|||
|
||||
export type LiteralType = BaseType & {
|
||||
kind: 'literal',
|
||||
value: string | number | boolean | null | void,
|
||||
value: LiteralValue,
|
||||
};
|
||||
|
||||
export type LiteralValue = string | number | boolean | null | void;
|
||||
|
||||
export type AnyType = BaseType & {
|
||||
kind: 'any',
|
||||
};
|
||||
|
@ -93,20 +101,20 @@ export type ReferenceType = BaseType & {
|
|||
to: TypeId,
|
||||
};
|
||||
|
||||
export const createRecord = (fields: *): RecordType => ({kind: 'record', fields});
|
||||
export const createArray = (items: *): ArrayType => ({kind: 'array', items});
|
||||
export const createTuple = (items: *): TupleType => ({kind: 'tuple', items});
|
||||
export const createMap = (keys: *, values: *): MapType => ({kind: 'map', keys, values});
|
||||
export const createUnion = (variants: *): UnionType => ({kind: 'union', variants});
|
||||
export const createIntersection = (parts: *): IntersectionType => ({kind: 'intersection', parts});
|
||||
export const createMaybe = (value: *): MaybeType => ({kind: 'maybe', value});
|
||||
export const createNumber = (repr: *): NumberType => ({kind: 'number', repr});
|
||||
export const createRecord = (fields: Field[]): RecordType => ({kind: 'record', fields});
|
||||
export const createArray = (items: Type): ArrayType => ({kind: 'array', items});
|
||||
export const createTuple = (items: Array<?Type>): TupleType => ({kind: 'tuple', items});
|
||||
export const createMap = (keys: Type, values: Type): MapType => ({kind: 'map', keys, values});
|
||||
export const createUnion = (variants: Type[]): UnionType => ({kind: 'union', variants});
|
||||
export const createIntersection = (parts: Type[]): IntersectionType => ({kind: 'intersection', parts});
|
||||
export const createMaybe = (value: Type): MaybeType => ({kind: 'maybe', value});
|
||||
export const createNumber = (repr: Repr): NumberType => ({kind: 'number', repr});
|
||||
export const createString = (): StringType => ({kind: 'string'});
|
||||
export const createBoolean = (): BooleanType => ({kind: 'boolean'});
|
||||
export const createLiteral = (value: *): LiteralType => ({kind: 'literal', value});
|
||||
export const createLiteral = (value: LiteralValue): LiteralType => ({kind: 'literal', value});
|
||||
export const createAny = () => ({kind: 'any'});
|
||||
export const createMixed = () => ({kind: 'mixed'});
|
||||
export const createReference = (to: *) => ({kind: 'reference', to});
|
||||
export const createReference = (to: TypeId) => ({kind: 'reference', to});
|
||||
|
||||
declare function clone(Type): Type;
|
||||
declare function clone(TypeId): TypeId;
|
||||
|
@ -162,3 +170,7 @@ function cloneType(type: Type): Type {
|
|||
return createReference(type.to.slice());
|
||||
}
|
||||
}
|
||||
|
||||
export function isRepr(v: string): boolean %checks {
|
||||
return v === 'i32' || v === 'i64' || v === 'u32' || v === 'u64' || v === 'f32' || v === 'f64';
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
// I so much dream about the user guards...
|
||||
|
|
55
tests/run.js
55
tests/run.js
|
@ -1,20 +1,23 @@
|
|||
// @flow
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as yaml from 'yaml-js';
|
||||
import wu from 'wu';
|
||||
import Ajv from 'ajv';
|
||||
import stringifyJson from 'json-stringify-pretty-compact';
|
||||
|
||||
import collect from '../src';
|
||||
|
||||
function run(title) {
|
||||
function run(title, generateMissing) {
|
||||
let actual, expectedTypes, expectedSchema;
|
||||
|
||||
// Run the collector only if the suite will be checked.
|
||||
before(() => {
|
||||
actual = collect(title + '/source.js');
|
||||
expectedTypes = yaml.load(fs.readFileSync(title + '/types.yaml', 'utf8'));
|
||||
expectedSchema = JSON.parse(fs.readFileSync(title + '/schema.json', 'utf8'));
|
||||
expectedTypes = readFileAndPrepare(title + '/types.yaml', yaml.load);
|
||||
expectedSchema = readFileAndPrepare(title + '/schema.json', JSON.parse);
|
||||
});
|
||||
|
||||
it('should not include cycles', () => {
|
||||
|
@ -22,7 +25,18 @@ function run(title) {
|
|||
});
|
||||
|
||||
it('should provide expected types', () => {
|
||||
assert.deepEqual(actual.types, expectedTypes);
|
||||
if (expectedTypes === undefined && generateMissing) {
|
||||
console.log('Generating types.yaml...');
|
||||
|
||||
const content = yaml.dump(actual.types, null, null, {
|
||||
indent: 4,
|
||||
width: 100,
|
||||
}).trimRight();
|
||||
|
||||
fs.writeFileSync(title + '/types.yaml', content);
|
||||
} else {
|
||||
assert.deepEqual(actual.types, expectedTypes);
|
||||
}
|
||||
});
|
||||
|
||||
it('should generate valid JSON schema', () => {
|
||||
|
@ -34,10 +48,37 @@ function run(title) {
|
|||
});
|
||||
|
||||
it('should provide expected JSON schema', () => {
|
||||
assert.deepEqual(actual.schema, expectedSchema);
|
||||
if (expectedSchema === undefined && generateMissing) {
|
||||
console.log('Generating schema.json...');
|
||||
|
||||
const content = stringifyJson(actual.schema, {
|
||||
indent: 4,
|
||||
maxLength: 100,
|
||||
});
|
||||
|
||||
fs.writeFileSync(title + '/schema.json', content);
|
||||
} else {
|
||||
assert.deepEqual(actual.schema, expectedSchema);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function readFileAndPrepare<R>(path: string, prepare: string => R): R | void {
|
||||
let data;
|
||||
|
||||
try {
|
||||
data = fs.readFileSync(path, 'utf8');
|
||||
} catch (ex) {
|
||||
if (ex.code === 'ENOENT') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return prepare(data);
|
||||
}
|
||||
|
||||
function detectCycles(obj: mixed, cycles: Set<mixed> = new Set, objs: Set<mixed> = new Set) {
|
||||
if (obj == null || typeof obj !== 'object') {
|
||||
return cycles;
|
||||
|
@ -61,8 +102,10 @@ function detectCycles(obj: mixed, cycles: Set<mixed> = new Set, objs: Set<mixed>
|
|||
function main() {
|
||||
process.chdir(path.join(__dirname, 'samples'));
|
||||
|
||||
const generateMissing = process.env.GENERATE_MISSING === '1';
|
||||
|
||||
for (const title of fs.readdirSync('.')) {
|
||||
describe(title, () => run(title));
|
||||
describe(title, () => run(title, generateMissing));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-06/schema#",
|
||||
"definitions": {
|
||||
"fixMe::X": true,
|
||||
"fixMe::Y": {
|
||||
"type": "object",
|
||||
"properties": {"y": true},
|
||||
"required": ["y"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
type X = $FlowFixMe;
|
||||
|
||||
type Y = {
|
||||
y: $FlowFixMe;
|
||||
};
|
||||
|
||||
export {X, Y};
|
|
@ -0,0 +1,8 @@
|
|||
- kind: any
|
||||
id: [fixMe, X]
|
||||
- kind: record
|
||||
fields:
|
||||
- name: y
|
||||
value: {kind: any}
|
||||
required: true
|
||||
id: [fixMe, Y]
|
|
@ -0,0 +1,15 @@
|
|||
export type A = {
|
||||
a: number;
|
||||
}
|
||||
|
||||
export type IgnoredType = {
|
||||
ignored: number,
|
||||
};
|
||||
|
||||
export interface IgnoredInterface {
|
||||
ignored: number;
|
||||
}
|
||||
|
||||
export default class IgnoredDefault {
|
||||
ignored: number;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-06/schema#",
|
||||
"definitions": {
|
||||
"selectiveImport::modules::first::A": {
|
||||
"type": "object",
|
||||
"properties": {"a": {"type": "number"}},
|
||||
"required": ["a"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import {A} from './modules/first';
|
||||
|
||||
export {A};
|
|
@ -0,0 +1,6 @@
|
|||
- kind: record
|
||||
fields:
|
||||
- name: a
|
||||
value: {kind: number, repr: f64}
|
||||
required: true
|
||||
id: [selectiveImport, modules, first, A]
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-06/schema#",
|
||||
"definitions": {
|
||||
"stringKeys::X": {
|
||||
"type": "object",
|
||||
"properties": {"a b": {"type": "string"}},
|
||||
"required": ["a b"]
|
||||
},
|
||||
"stringKeys::Y": {
|
||||
"type": "object",
|
||||
"properties": {"a b": {"type": "string"}},
|
||||
"required": ["a b"]
|
||||
},
|
||||
"stringKeys::Z": {
|
||||
"type": "object",
|
||||
"properties": {"a b": {"type": "string"}},
|
||||
"required": ["a b"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
type X = {
|
||||
'a b': string;
|
||||
};
|
||||
|
||||
interface Y {
|
||||
'a b': string;
|
||||
}
|
||||
|
||||
class Z {
|
||||
'a b': string;
|
||||
}
|
||||
|
||||
export {X, Y, Z};
|
|
@ -0,0 +1,18 @@
|
|||
- kind: record
|
||||
fields:
|
||||
- name: "a b"
|
||||
value: {kind: string}
|
||||
required: true
|
||||
id: [stringKeys, X]
|
||||
- kind: record
|
||||
fields:
|
||||
- name: "a b"
|
||||
value: {kind: string}
|
||||
required: true
|
||||
id: [stringKeys, Y]
|
||||
- kind: record
|
||||
fields:
|
||||
- name: "a b"
|
||||
value: {kind: string}
|
||||
required: true
|
||||
id: [stringKeys, Z]
|
Loading…
Reference in New Issue