diff --git a/packages/babel-types/scripts/generators/flow.js b/packages/babel-types/scripts/generators/flow.js index 2a91703353db..e8039ae13b8a 100644 --- a/packages/babel-types/scripts/generators/flow.js +++ b/packages/babel-types/scripts/generators/flow.js @@ -8,23 +8,28 @@ const NODE_PREFIX = "BabelNode"; let code = `// NOTE: This file is autogenerated. Do not modify. // See packages/babel-types/scripts/generators/flow.js for script used. +// @flow -declare class ${NODE_PREFIX}Comment { +declare type ${NODE_PREFIX}BaseComment = {| value: string; start: number; end: number; loc: ${NODE_PREFIX}SourceLocation; -} +|}; -declare class ${NODE_PREFIX}CommentBlock extends ${NODE_PREFIX}Comment { +declare type ${NODE_PREFIX}CommentBlock = {| + ...${NODE_PREFIX}BaseComment; type: "CommentBlock"; -} +|}; -declare class ${NODE_PREFIX}CommentLine extends ${NODE_PREFIX}Comment { +declare type ${NODE_PREFIX}CommentLine ={| + ...${NODE_PREFIX}BaseComment, type: "CommentLine"; -} +|}; -declare class ${NODE_PREFIX}SourceLocation { +declare type ${NODE_PREFIX}Comment = ${NODE_PREFIX}CommentBlock | ${NODE_PREFIX}CommentLine; + +declare type ${NODE_PREFIX}SourceLocation = {| start: { line: number; column: number; @@ -46,8 +51,6 @@ declare class ${NODE_PREFIX} { extra?: { [string]: mixed }; }\n\n`; -// - const lines = []; for (const type in t.NODE_FIELDS) { @@ -91,167 +94,202 @@ for (const type in t.NODE_FIELDS) { } }); - code += `declare class ${NODE_PREFIX}${type} extends ${NODE_PREFIX} { + // Flow seems to deoptimize the union type if another type is spread into the node declaration. + // Defining the base props over and over again significantely speeds up the type checking. + code += `declare type ${NODE_PREFIX}${type} = {| + leadingComments?: Array<${NODE_PREFIX}Comment>; + innerComments?: Array<${NODE_PREFIX}Comment>; + trailingComments?: Array<${NODE_PREFIX}Comment>; + start: ?number; + end: ?number; + loc: ?${NODE_PREFIX}SourceLocation, ${struct.join("\n ").trim()} -}\n\n`; +|};\n\n`; // Flow chokes on super() and import() :/ if (type !== "Super" && type !== "Import") { lines.push( - `declare function ${toFunctionName(type)}(${args.join( + `declare export function ${toFunctionName(type)}(${args.join( ", " )}): ${NODE_PREFIX}${type};` ); } else { const functionName = toFunctionName(type); lines.push( - `declare function _${functionName}(${args.join( + `declare var _${functionName}: (${args.join( ", " - )}): ${NODE_PREFIX}${type};`, + )}) => ${NODE_PREFIX}${type};`, `declare export { _${functionName} as ${functionName} }` ); } } +const assertFunctions = []; + for (const typeName of t.TYPES) { const isDeprecated = !!t.DEPRECATED_KEYS[typeName]; const realName = isDeprecated ? t.DEPRECATED_KEYS[typeName] : typeName; - let decl = `declare function is${typeName}(node: ?Object, opts?: ?Object): boolean`; + let decl = `declare export function is${typeName}(node: ?Object, opts?: ?Object): boolean`; + if (t.NODE_FIELDS[realName]) { - decl += ` %checks (node instanceof ${NODE_PREFIX}${realName})`; + decl += ` %checks (node != null && node.type === '${realName}');`; + } else if (t.FLIPPED_ALIAS_KEYS[typeName]) { + const types = t.FLIPPED_ALIAS_KEYS[typeName]; + const checks = types.map(t => `node.type === '${t}'`).join(" || "); + decl += ` %checks (node != null && (${checks}));`; + } else { + decl += ";"; } lines.push(decl); - lines.push( - `declare function assert${typeName}(node: ?Object, opts?: ?Object): void` + assertFunctions.push( + `declare export function assert${typeName}(node: ?Object, opts?: ?Object): void;` ); } lines.push( // assert/ `declare function assertNode(obj: any): void`, + ...assertFunctions, // builders/ // eslint-disable-next-line max-len - `declare function createTypeAnnotationBasedOnTypeof(type: 'string' | 'number' | 'undefined' | 'boolean' | 'function' | 'object' | 'symbol'): ${NODE_PREFIX}TypeAnnotation`, + `declare export function createTypeAnnotationBasedOnTypeof(type: 'string' | 'number' | 'undefined' | 'boolean' | 'function' | 'object' | 'symbol'): ${NODE_PREFIX}TypeAnnotation`, // eslint-disable-next-line max-len - `declare function createUnionTypeAnnotation(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`, + `declare export function createUnionTypeAnnotation(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`, // eslint-disable-next-line max-len - `declare function createFlowUnionType(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`, + `declare export function createFlowUnionType(types: Array<${NODE_PREFIX}FlowType>): ${NODE_PREFIX}UnionTypeAnnotation`, // this smells like "internal API" // eslint-disable-next-line max-len - `declare function buildChildren(node: { children: Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment | ${NODE_PREFIX}JSXEmptyExpression> }): Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment>`, + `declare export function buildChildren(node: { children: Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment | ${NODE_PREFIX}JSXEmptyExpression> }): Array<${NODE_PREFIX}JSXText | ${NODE_PREFIX}JSXExpressionContainer | ${NODE_PREFIX}JSXSpreadChild | ${NODE_PREFIX}JSXElement | ${NODE_PREFIX}JSXFragment>`, // clone/ - `declare function clone(n: T): T;`, - `declare function cloneDeep(n: T): T;`, - `declare function cloneDeepWithoutLoc(n: T): T;`, - `declare function cloneNode(n: T, deep?: boolean, withoutLoc?: boolean): T;`, - `declare function cloneWithoutLoc(n: T): T;`, + `declare export function clone(n: T): T;`, + `declare export function cloneDeep(n: T): T;`, + `declare export function cloneDeepWithoutLoc(n: T): T;`, + `declare export function cloneNode(n: T, deep?: boolean, withoutLoc?: boolean): T;`, + `declare export function cloneWithoutLoc(n: T): T;`, // comments/ `declare type CommentTypeShorthand = 'leading' | 'inner' | 'trailing'`, // eslint-disable-next-line max-len - `declare function addComment(node: T, type: CommentTypeShorthand, content: string, line?: boolean): T`, + `declare export function addComment(node: T, type: CommentTypeShorthand, content: string, line?: boolean): T`, // eslint-disable-next-line max-len - `declare function addComments(node: T, type: CommentTypeShorthand, comments: Array): T`, - `declare function inheritInnerComments(node: Node, parent: Node): void`, - `declare function inheritLeadingComments(node: Node, parent: Node): void`, - `declare function inheritsComments(node: T, parent: Node): void`, - `declare function inheritTrailingComments(node: Node, parent: Node): void`, - `declare function removeComments(node: T): T`, + `declare export function addComments(node: T, type: CommentTypeShorthand, comments: Array): T`, + `declare export function inheritInnerComments(node: Node, parent: Node): void`, + `declare export function inheritLeadingComments(node: Node, parent: Node): void`, + `declare export function inheritsComments(node: T, parent: Node): void`, + `declare export function inheritTrailingComments(node: Node, parent: Node): void`, + `declare export function removeComments(node: T): T`, // converters/ - `declare function ensureBlock(node: ${NODE_PREFIX}, key: string): ${NODE_PREFIX}BlockStatement`, - `declare function toBindingIdentifierName(name?: ?string): string`, + `declare export function ensureBlock(node: ${NODE_PREFIX}, key: string): ${NODE_PREFIX}BlockStatement`, + `declare export function toBindingIdentifierName(name?: ?string): string`, // eslint-disable-next-line max-len - `declare function toBlock(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Expression, parent?: ${NODE_PREFIX}Function | null): ${NODE_PREFIX}BlockStatement`, + `declare export function toBlock(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Expression, parent?: ${NODE_PREFIX}Function | null): ${NODE_PREFIX}BlockStatement`, // eslint-disable-next-line max-len - `declare function toComputedKey(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}Expression | ${NODE_PREFIX}Identifier): ${NODE_PREFIX}Expression`, + `declare export function toComputedKey(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}Expression | ${NODE_PREFIX}Identifier): ${NODE_PREFIX}Expression`, // eslint-disable-next-line max-len - `declare function toExpression(node: ${NODE_PREFIX}ExpressionStatement | ${NODE_PREFIX}Expression | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function): ${NODE_PREFIX}Expression`, - `declare function toIdentifier(name?: ?string): string`, + `declare export function toExpression(node: ${NODE_PREFIX}ExpressionStatement | ${NODE_PREFIX}Expression | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function): ${NODE_PREFIX}Expression`, + `declare export function toIdentifier(name?: ?string): string`, // eslint-disable-next-line max-len - `declare function toKeyAlias(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}): string`, + `declare export function toKeyAlias(node: ${NODE_PREFIX}Method | ${NODE_PREFIX}Property, key?: ${NODE_PREFIX}): string`, // toSequenceExpression relies on types that aren't declared in flow // eslint-disable-next-line max-len - `declare function toStatement(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function | ${NODE_PREFIX}AssignmentExpression, ignore?: boolean): ${NODE_PREFIX}Statement | void`, - `declare function valueToNode(value: any): ${NODE_PREFIX}Expression`, + `declare export function toStatement(node: ${NODE_PREFIX}Statement | ${NODE_PREFIX}Class | ${NODE_PREFIX}Function | ${NODE_PREFIX}AssignmentExpression, ignore?: boolean): ${NODE_PREFIX}Statement | void`, + `declare export function valueToNode(value: any): ${NODE_PREFIX}Expression`, // modifications/ // eslint-disable-next-line max-len - `declare function removeTypeDuplicates(types: Array<${NODE_PREFIX}FlowType>): Array<${NODE_PREFIX}FlowType>`, + `declare export function removeTypeDuplicates(types: Array<${NODE_PREFIX}FlowType>): Array<${NODE_PREFIX}FlowType>`, // eslint-disable-next-line max-len - `declare function appendToMemberExpression(member: ${NODE_PREFIX}MemberExpression, append: ${NODE_PREFIX}, computed?: boolean): ${NODE_PREFIX}MemberExpression`, + `declare export function appendToMemberExpression(member: ${NODE_PREFIX}MemberExpression, append: ${NODE_PREFIX}, computed?: boolean): ${NODE_PREFIX}MemberExpression`, // eslint-disable-next-line max-len - `declare function inherits(child: T, parent: ${NODE_PREFIX} | null | void): T`, + `declare export function inherits(child: T, parent: ${NODE_PREFIX} | null | void): T`, // eslint-disable-next-line max-len - `declare function prependToMemberExpression(member: ${NODE_PREFIX}MemberExpression, prepend: ${NODE_PREFIX}Expression): ${NODE_PREFIX}MemberExpression`, - `declare function removeProperties(n: T, opts: ?{}): void;`, - `declare function removePropertiesDeep(n: T, opts: ?{}): T;`, + `declare export function prependToMemberExpression(member: ${NODE_PREFIX}MemberExpression, prepend: ${NODE_PREFIX}Expression): ${NODE_PREFIX}MemberExpression`, + `declare export function removeProperties(n: T, opts: ?{}): void;`, + `declare export function removePropertiesDeep(n: T, opts: ?{}): T;`, // retrievers/ // eslint-disable-next-line max-len - `declare function getBindingIdentifiers(node: ${NODE_PREFIX}, duplicates: boolean, outerOnly?: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`, + `declare export function getBindingIdentifiers(node: ${NODE_PREFIX}, duplicates: boolean, outerOnly?: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`, // eslint-disable-next-line max-len - `declare function getOuterBindingIdentifiers(node: Node, duplicates: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`, + `declare export function getOuterBindingIdentifiers(node: Node, duplicates: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`, // traverse/ - `declare type TraversalAncestors = Array<{ + `declare export type TraversalAncestors = Array<{ node: BabelNode, key: string, index?: number, }>; - declare type TraversalHandler = (BabelNode, TraversalAncestors, T) => void; - declare type TraversalHandlers = { + declare export type TraversalHandler = (BabelNode, TraversalAncestors, T) => void; + declare export type TraversalHandlers = { enter?: TraversalHandler, exit?: TraversalHandler, };`.replace(/(^|\n) {2}/g, "$1"), // eslint-disable-next-line - `declare function traverse(n: BabelNode, TraversalHandler | TraversalHandlers, state?: T): void;`, - `declare function traverseFast(n: Node, h: TraversalHandler, state?: T): void;`, + `declare export function traverse(n: BabelNode, TraversalHandler | TraversalHandlers, state?: T): void;`, + `declare export function traverseFast(n: Node, h: TraversalHandler, state?: T): void;`, // utils/ // cleanJSXElementLiteralChild is not exported // inherit is not exported - `declare function shallowEqual(actual: Object, expected: Object): boolean`, + `declare export function shallowEqual(actual: Object, expected: Object): boolean`, // validators/ // eslint-disable-next-line max-len - `declare function buildMatchMemberExpression(match: string, allowPartial?: boolean): (?BabelNode) => boolean`, - `declare function is(type: string, n: BabelNode, opts: Object): boolean;`, - `declare function isBinding(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`, - `declare function isBlockScoped(node: BabelNode): boolean`, - `declare function isImmutable(node: BabelNode): boolean`, - `declare function isLet(node: BabelNode): boolean`, - `declare function isNode(node: ?Object): boolean`, - `declare function isNodesEquivalent(a: any, b: any): boolean`, - `declare function isPlaceholderType(placeholderType: string, targetType: string): boolean`, - `declare function isReferenced(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`, - `declare function isScope(node: BabelNode, parent: BabelNode): boolean`, - `declare function isSpecifierDefault(specifier: BabelNodeModuleSpecifier): boolean`, - `declare function isType(nodetype: ?string, targetType: string): boolean`, - `declare function isValidES3Identifier(name: string): boolean`, - `declare function isValidES3Identifier(name: string): boolean`, - `declare function isValidIdentifier(name: string): boolean`, - `declare function isVar(node: BabelNode): boolean`, + `declare export function buildMatchMemberExpression(match: string, allowPartial?: boolean): (?BabelNode) => boolean`, + `declare export function is(type: string, n: BabelNode, opts: Object): boolean;`, + `declare export function isBinding(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`, + `declare export function isBlockScoped(node: BabelNode): boolean`, + `declare export function isLet(node: BabelNode): boolean %checks (node.type === 'VariableDeclaration')`, + `declare export function isNode(node: ?Object): boolean`, + `declare export function isNodesEquivalent(a: any, b: any): boolean`, + `declare export function isPlaceholderType(placeholderType: string, targetType: string): boolean`, + `declare export function isReferenced(node: BabelNode, parent: BabelNode, grandparent?: BabelNode): boolean`, + `declare export function isScope(node: BabelNode, parent: BabelNode): boolean %checks (node.type === 'BlockStatement' || node.type === 'CatchClause' || node.type === 'DoWhileStatement' || node.type === 'ForInStatement' || node.type === 'ForStatement' || node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'Program' || node.type === 'ObjectMethod' || node.type === 'SwitchStatement' || node.type === 'WhileStatement' || node.type === 'ArrowFunctionExpression' || node.type === 'ClassExpression' || node.type === 'ClassDeclaration' || node.type === 'ForOfStatement' || node.type === 'ClassMethod' || node.type === 'ClassPrivateMethod' || node.type === 'TSModuleBlock')`, + `declare export function isSpecifierDefault(specifier: BabelNodeModuleSpecifier): boolean`, + `declare export function isType(nodetype: ?string, targetType: string): boolean`, + `declare export function isValidES3Identifier(name: string): boolean`, + `declare export function isValidES3Identifier(name: string): boolean`, + `declare export function isValidIdentifier(name: string): boolean`, + `declare export function isVar(node: BabelNode): boolean %checks (node.type === 'VariableDeclaration')`, // eslint-disable-next-line max-len - `declare function matchesPattern(node: ?BabelNode, match: string | Array, allowPartial?: boolean): boolean`, - `declare function validate(n: BabelNode, key: string, value: mixed): void;` + `declare export function matchesPattern(node: ?BabelNode, match: string | Array, allowPartial?: boolean): boolean`, + `declare export function validate(n: BabelNode, key: string, value: mixed): void;` ); +code += `declare type ${NODE_PREFIX} = ${Object.keys(t.NODE_FIELDS) + .map(type => `${NODE_PREFIX}${type}`) + .join(" | ")};\n`; + for (const type in t.FLIPPED_ALIAS_KEYS) { const types = t.FLIPPED_ALIAS_KEYS[type]; - code += `type ${NODE_PREFIX}${type} = ${types + code += `declare type ${NODE_PREFIX}${type} = ${types .map(type => `${NODE_PREFIX}${type}`) .join(" | ")};\n`; } +// Module level exports without NODE_PREFIX prefix +const aliasedTypes = [ + "CommentBlock", + "CommentLine", + "Comment", + "SourceLocation", + ...Object.keys(t.NODE_FIELDS), + ...Object.keys(t.FLIPPED_ALIAS_KEYS), +]; +lines.push( + `declare export type Node = ${NODE_PREFIX};`, + ...aliasedTypes.map( + type => `declare export type ${type} = ${NODE_PREFIX}${type};` + ) +); + code += `\ndeclare module "@babel/types" { ${lines.join("\n").replace(/\n/g, "\n ").trim()} }\n`; -// - process.stdout.write(code);