"use strict"; const t = require("../../"); const stringifyValidator = require("../utils/stringifyValidator"); const toFunctionName = require("../utils/toFunctionName"); 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. declare class ${NODE_PREFIX}Comment { value: string; start: number; end: number; loc: ${NODE_PREFIX}SourceLocation; } declare class ${NODE_PREFIX}CommentBlock extends ${NODE_PREFIX}Comment { type: "CommentBlock"; } declare class ${NODE_PREFIX}CommentLine extends ${NODE_PREFIX}Comment { type: "CommentLine"; } 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 = []; const builderNames = t.BUILDER_KEYS[type]; 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 = stringifyValidator(validate, NODE_PREFIX); } if (typeAnnotation) { suffix += ": " + typeAnnotation; } if (builderNames.includes(fieldName)) { 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 ${toFunctionName(type)}(${args.join( ", " )}): ${NODE_PREFIX}${type};` ); } else { const functionName = toFunctionName(type); lines.push( `declare function _${functionName}(${args.join( ", " )}): ${NODE_PREFIX}${type};`, `declare export { _${functionName} as ${functionName} }` ); } } 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( // builders/ // eslint-disable-next-line max-len `declare 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`, // 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>`, // 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;`, // 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`, // 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`, // converters/ `declare function ensureBlock(node: ${NODE_PREFIX}, key: string): ${NODE_PREFIX}BlockStatement`, `declare 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`, // 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`, // 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`, // eslint-disable-next-line max-len `declare 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`, // modifications/ // eslint-disable-next-line max-len `declare 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`, // eslint-disable-next-line max-len `declare 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;`, // 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> }`, // eslint-disable-next-line max-len `declare function getOuterBindingIdentifiers(node: Node, duplicates: boolean): { [key: string]: ${NODE_PREFIX}Identifier | Array<${NODE_PREFIX}Identifier> }`, // traverse/ `declare type TraversalAncestors = Array<{ node: BabelNode, key: string, index?: number, }>; declare type TraversalHandler = (BabelNode, TraversalAncestors, T) => void; declare 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;`, // utils/ // cleanJSXElementLiteralChild is not exported // inherit is not exported `declare 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`, // 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;` ); 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);