Generate TypeScript typings, and improve generated Flow typings (#7101)
* generate typescript types * improve type generator output * move generator scripts to scripts/generators * use new stringifier for generating flow types too * export summary types * add support for oneOfNodeOrValueTypes to improve type generation * export typescript types from top level, and remove module declaration * generate typescript/flow types and copy typescript types to babel-types/lib as part of make build * copy flow types to babel-types/lib as part of make build (fix #6839) * improve typing: Identifier->name should be a string, not any * avoid destructuring, to support node 4 * update doc generator to share more code, regenerate babel-types readme, pipe all generator output to stdout * regenerate babel-types readme as part of make build * improve typing: ClassProperty->key should be Identifier | StringLiteral | NumericLiteral | Expression, not any * improve typing: optional node properties are nullable, not undefinedable * improve docs: FlowClassImplements should be ClassImplements * make ts usage more friendly: when using babel-types api, make optional params | undefined, and when reading nodes keep optional params | null * rm lib/types.d.ts and lib/types.js in favor of packages/babel-types/lib * add missing variance node type, address review comments * add tests for flow variance * Comment should be a disjoint union of tagged types * update .flowconfig
This commit is contained in:
152
scripts/generators/flow.js
Normal file
152
scripts/generators/flow.js
Normal file
@@ -0,0 +1,152 @@
|
||||
"use strict";
|
||||
|
||||
const t = require("../../packages/babel-types");
|
||||
const utils = require("./utils");
|
||||
|
||||
const NODE_PREFIX = "BabelNode";
|
||||
|
||||
let code = `// NOTE: This file is autogenerated. Do not modify.
|
||||
// See scripts/generators/flow.js for script used.
|
||||
|
||||
declare class ${NODE_PREFIX}Comment {
|
||||
value: string;
|
||||
start: number;
|
||||
end: number;
|
||||
loc: ${NODE_PREFIX}SourceLocation;
|
||||
}
|
||||
|
||||
declare class ${NODE_PREFIX}BlockComment extends ${NODE_PREFIX}Comment {
|
||||
type: "BlockComment";
|
||||
}
|
||||
|
||||
declare class ${NODE_PREFIX}LineComment extends ${NODE_PREFIX}Comment {
|
||||
type: "LineComment";
|
||||
}
|
||||
|
||||
declare class ${NODE_PREFIX}SourceLocation {
|
||||
start: {
|
||||
line: number;
|
||||
column: number;
|
||||
};
|
||||
|
||||
end: {
|
||||
line: number;
|
||||
column: number;
|
||||
};
|
||||
}
|
||||
|
||||
declare class ${NODE_PREFIX} {
|
||||
leadingComments: ?Array<${NODE_PREFIX}Comment>;
|
||||
innerComments: ?Array<${NODE_PREFIX}Comment>;
|
||||
trailingComments: ?Array<${NODE_PREFIX}Comment>;
|
||||
start: ?number;
|
||||
end: ?number;
|
||||
loc: ?${NODE_PREFIX}SourceLocation;
|
||||
}\n\n`;
|
||||
|
||||
//
|
||||
|
||||
const lines = [];
|
||||
|
||||
for (const type in t.NODE_FIELDS) {
|
||||
const fields = t.NODE_FIELDS[type];
|
||||
|
||||
const struct = ['type: "' + type + '";'];
|
||||
const args = [];
|
||||
|
||||
Object.keys(t.NODE_FIELDS[type])
|
||||
.sort((fieldA, fieldB) => {
|
||||
const indexA = t.BUILDER_KEYS[type].indexOf(fieldA);
|
||||
const indexB = t.BUILDER_KEYS[type].indexOf(fieldB);
|
||||
if (indexA === indexB) return fieldA < fieldB ? -1 : 1;
|
||||
if (indexA === -1) return 1;
|
||||
if (indexB === -1) return -1;
|
||||
return indexA - indexB;
|
||||
})
|
||||
.forEach(fieldName => {
|
||||
const field = fields[fieldName];
|
||||
|
||||
let suffix = "";
|
||||
if (field.optional || field.default != null) suffix += "?";
|
||||
|
||||
let typeAnnotation = "any";
|
||||
|
||||
const validate = field.validate;
|
||||
if (validate) {
|
||||
typeAnnotation = utils.stringifyValidator(validate, NODE_PREFIX);
|
||||
}
|
||||
|
||||
if (typeAnnotation) {
|
||||
suffix += ": " + typeAnnotation;
|
||||
}
|
||||
|
||||
args.push(t.toBindingIdentifierName(fieldName) + suffix);
|
||||
|
||||
if (t.isValidIdentifier(fieldName)) {
|
||||
struct.push(fieldName + suffix + ";");
|
||||
}
|
||||
});
|
||||
|
||||
code += `declare class ${NODE_PREFIX}${type} extends ${NODE_PREFIX} {
|
||||
${struct.join("\n ").trim()}
|
||||
}\n\n`;
|
||||
|
||||
// Flow chokes on super() and import() :/
|
||||
if (type !== "Super" && type !== "Import") {
|
||||
lines.push(
|
||||
`declare function ${utils.toFunctionName(type)}(${args.join(
|
||||
", "
|
||||
)}): ${NODE_PREFIX}${type};`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < t.TYPES.length; i++) {
|
||||
let decl = `declare function is${
|
||||
t.TYPES[i]
|
||||
}(node: Object, opts?: ?Object): boolean`;
|
||||
|
||||
if (t.NODE_FIELDS[t.TYPES[i]]) {
|
||||
decl += ` %checks (node instanceof ${NODE_PREFIX}${t.TYPES[i]})`;
|
||||
}
|
||||
|
||||
lines.push(decl);
|
||||
}
|
||||
|
||||
lines.push(
|
||||
`declare function validate(n: BabelNode, key: string, value: mixed): void;`,
|
||||
`declare function clone<T>(n: T): T;`,
|
||||
`declare function cloneDeep<T>(n: T): T;`,
|
||||
`declare function removeProperties<T>(n: T, opts: ?{}): void;`,
|
||||
`declare function removePropertiesDeep<T>(n: T, opts: ?{}): T;`,
|
||||
`declare type TraversalAncestors = Array<{
|
||||
node: BabelNode,
|
||||
key: string,
|
||||
index?: number,
|
||||
}>;
|
||||
declare type TraversalHandler<T> = (BabelNode, TraversalAncestors, T) => void;
|
||||
declare type TraversalHandlers<T> = {
|
||||
enter?: TraversalHandler<T>,
|
||||
exit?: TraversalHandler<T>,
|
||||
};`.replace(/(^|\n) {2}/g, "$1"),
|
||||
// eslint-disable-next-line
|
||||
`declare function traverse<T>(n: BabelNode, TraversalHandler<T> | TraversalHandlers<T>, state?: T): void;`
|
||||
);
|
||||
|
||||
for (const type in t.FLIPPED_ALIAS_KEYS) {
|
||||
const types = t.FLIPPED_ALIAS_KEYS[type];
|
||||
code += `type ${NODE_PREFIX}${type} = ${types
|
||||
.map(type => `${NODE_PREFIX}${type}`)
|
||||
.join(" | ")};\n`;
|
||||
}
|
||||
|
||||
code += `\ndeclare module "@babel/types" {
|
||||
${lines
|
||||
.join("\n")
|
||||
.replace(/\n/g, "\n ")
|
||||
.trim()}
|
||||
}\n`;
|
||||
|
||||
//
|
||||
|
||||
process.stdout.write(code);
|
||||
Reference in New Issue
Block a user