import util from "util"; import stringifyValidator from "../utils/stringifyValidator.js"; import toFunctionName from "../utils/toFunctionName.js"; import t from "../../lib/index.js"; const readme = [ `--- id: babel-types title: @babel/types --- > This module contains methods for building ASTs manually and for checking the types of AST nodes. ## Install \`\`\`sh npm install --save-dev @babel/types \`\`\` ## API`, ]; const customTypes = { ClassMethod: { key: "if computed then `Expression` else `Identifier | Literal`", }, Identifier: { name: "`string`", }, MemberExpression: { property: "if computed then `Expression` else `Identifier`", }, ObjectMethod: { key: "if computed then `Expression` else `Identifier | Literal`", }, ObjectProperty: { key: "if computed then `Expression` else `Identifier | Literal`", }, ClassPrivateMethod: { computed: "'false'", }, ClassPrivateProperty: { computed: "'false'", }, }; const APIHistory = { ClassProperty: [["v7.6.0", "Supports `static`"]], }; function formatHistory(historyItems) { const lines = historyItems.map( item => "| `" + item[0] + "` | " + item[1] + " |" ); return [ "
", " History", "| Version | Changes |", "| --- | --- |", ...lines, "
", ]; } function printAPIHistory(key, readme) { if (APIHistory[key]) { readme.push(""); readme.push(...formatHistory(APIHistory[key])); } } function printNodeFields(key, readme) { if (Object.keys(t.NODE_FIELDS[key]).length > 0) { readme.push(""); readme.push("AST Node `" + key + "` shape:"); Object.keys(t.NODE_FIELDS[key]) .sort(function (fieldA, fieldB) { const indexA = t.BUILDER_KEYS[key].indexOf(fieldA); const indexB = t.BUILDER_KEYS[key].indexOf(fieldB); if (indexA === indexB) return fieldA < fieldB ? -1 : 1; if (indexA === -1) return 1; if (indexB === -1) return -1; return indexA - indexB; }) .forEach(function (field) { const defaultValue = t.NODE_FIELDS[key][field].default; const fieldDescription = ["`" + field + "`"]; const validator = t.NODE_FIELDS[key][field].validate; if (customTypes[key] && customTypes[key][field]) { fieldDescription.push(`: ${customTypes[key][field]}`); } else if (validator) { try { fieldDescription.push( ": `" + stringifyValidator(validator, "") + "`" ); } catch (ex) { if (ex.code === "UNEXPECTED_VALIDATOR_TYPE") { console.log( "Unrecognised validator type for " + key + "." + field ); console.dir(ex.validator, { depth: 10, colors: true }); } } } if (defaultValue !== null || t.NODE_FIELDS[key][field].optional) { fieldDescription.push( " (default: `" + util.inspect(defaultValue) + "`" ); if (t.BUILDER_KEYS[key].indexOf(field) < 0) { fieldDescription.push(", excluded from builder function"); } fieldDescription.push(")"); } else { fieldDescription.push(" (required)"); } readme.push("- " + fieldDescription.join("")); }); } } function printAliasKeys(key, readme) { if (t.ALIAS_KEYS[key] && t.ALIAS_KEYS[key].length) { readme.push(""); readme.push( "Aliases: " + t.ALIAS_KEYS[key] .map(function (key) { return "[`" + key + "`](#" + key.toLowerCase() + ")"; }) .join(", ") ); } } readme.push("### Node Builders"); readme.push(""); Object.keys(t.BUILDER_KEYS) .sort() .forEach(function (key) { readme.push("#### " + toFunctionName(key)); readme.push(""); readme.push("```javascript"); readme.push( "t." + toFunctionName(key) + "(" + t.BUILDER_KEYS[key].join(", ") + ");" ); readme.push("```"); printAPIHistory(key, readme); readme.push(""); readme.push( "See also `t.is" + key + "(node, opts)` and `t.assert" + key + "(node, opts)`." ); printNodeFields(key, readme); printAliasKeys(key, readme); readme.push(""); readme.push("---"); readme.push(""); }); function generateMapAliasToNodeTypes() { const result = new Map(); for (const nodeType of Object.keys(t.ALIAS_KEYS)) { const aliases = t.ALIAS_KEYS[nodeType]; if (!aliases) continue; for (const alias of aliases) { if (!result.has(alias)) { result.set(alias, []); } const nodeTypes = result.get(alias); nodeTypes.push(nodeType); } } return result; } const aliasDescriptions = { Binary: "A cover of BinaryExpression and LogicalExpression, which share the same AST shape.", Block: "Deprecated. Will be removed in Babel 8.", BlockParent: "A cover of AST nodes that start an execution context with new [LexicalEnvironment](https://tc39.es/ecma262/#table-additional-state-components-for-ecmascript-code-execution-contexts). In other words, they define the scope of `let` and `const` declarations.", Class: "A cover of ClassExpression and ClassDeclaration, which share the same AST shape.", CompletionStatement: "A statement that indicates the [completion records](https://tc39.es/ecma262/#sec-completion-record-specification-type). In other words, they define the control flow of the program, such as when should a loop break or an action throws critical errors.", Conditional: "A cover of ConditionalExpression and IfStatement, which share the same AST shape.", Declaration: "A cover of any [Declaration](https://tc39.es/ecma262/#prod-Declaration)s.", EnumBody: "A cover of Flow enum bodies.", EnumMember: "A cover of Flow enum membors.", ExportDeclaration: "A cover of any [ExportDeclaration](https://tc39.es/ecma262/#prod-ExportDeclaration)s.", Expression: "A cover of any [Expression](https://tc39.es/ecma262/#sec-ecmascript-language-expressions)s.", ExpressionWrapper: "A wrapper of expression that does not have runtime semantics.", Flow: "A cover of AST nodes defined for Flow.", FlowBaseAnnotation: "A cover of primary Flow type annotations.", FlowDeclaration: "A cover of Flow declarations.", FlowPredicate: "A cover of Flow predicates.", FlowType: "A cover of Flow type annotations.", For: "A cover of [ForStatement](https://tc39.es/ecma262/#sec-for-statement)s and [ForXStatement](#forxstatement)s.", ForXStatement: "A cover of [ForInStatements and ForOfStatements](https://tc39.es/ecma262/#sec-for-in-and-for-of-statements).", Function: "A cover of functions and [method](#method)s, the must have `body` and `params`. Note: `Function` is different to `FunctionParent`. For example, a `StaticBlock` is a `FunctionParent` but not `Function`.", FunctionParent: "A cover of AST nodes that start an execution context with new [VariableEnvironment](https://tc39.es/ecma262/#table-additional-state-components-for-ecmascript-code-execution-contexts). In other words, they define the scope of `var` declarations. FunctionParent did not include `Program` since Babel 7.", Immutable: "A cover of immutable objects and JSX elements. An object is [immutable](https://tc39.es/ecma262/#immutable-prototype-exotic-object) if no other properties can be defined once created.", JSX: "A cover of AST nodes defined for [JSX](https://facebook.github.io/jsx/).", LVal: "A cover of left hand side expressions used in the `left` of assignment expressions and [ForXStatement](#forxstatement)s. ", Literal: "A cover of [Literal](https://tc39.es/ecma262/#sec-primary-expression-literals)s, [Regular Expression Literal](https://tc39.es/ecma262/#sec-primary-expression-regular-expression-literals)s and [Template Literal](https://tc39.es/ecma262/#sec-template-literals)s.", Loop: "A cover of loop statements.", Method: "A cover of object methods and class methods.", Miscellaneous: "A cover of non-standard AST types that are sometimes useful for development.", ModuleDeclaration: "A cover of ImportDeclaration and [ExportDeclaration](#exportdeclaration)", ModuleSpecifier: "A cover of import and export specifiers. Note: It is _not_ the [ModuleSpecifier](https://tc39.es/ecma262/#prod-ModuleSpecifier) defined in the spec.", ObjectMember: "A cover of [members](https://tc39.es/ecma262/#prod-PropertyDefinitionList) in an object literal.", Pattern: "A cover of [BindingPattern](https://tc39.es/ecma262/#prod-BindingPattern) except Identifiers.", PatternLike: "A cover of [BindingPattern](https://tc39.es/ecma262/#prod-BindingPattern)s. ", Private: "A cover of private class elements and private identifiers.", Property: "A cover of object properties and class properties.", Pureish: "A cover of AST nodes which do not have side-effects. In other words, there is no observable behaviour changes if they are evaluated more than once.", Scopable: "A cover of [FunctionParent](#functionparent) and [BlockParent](#blockparent).", Standardized: "A cover of AST nodes which are part of an official ECMAScript specification.", Statement: "A cover of any [Statement](https://tc39.es/ecma262/#prod-Statement)s.", TSBaseType: "A cover of primary TypeScript type annotations.", TSEntityName: "A cover of ts entities.", TSType: "A cover of TypeScript type annotations.", TSTypeElement: "A cover of TypeScript type declarations.", TypeScript: "A cover of AST nodes defined for TypeScript.", Terminatorless: "A cover of AST nodes whose semantic will change when a line terminator is inserted between the operator and the operand.", UnaryLike: "A cover of UnaryExpression and SpreadElement.", UserWhitespacable: "Deprecated. Will be removed in Babel 8.", While: "A cover of DoWhileStatement and WhileStatement, which share the same AST shape.", }; const mapAliasToNodeTypes = generateMapAliasToNodeTypes(); readme.push("### Aliases"); readme.push(""); for (const alias of [...mapAliasToNodeTypes.keys()].sort()) { const nodeTypes = mapAliasToNodeTypes.get(alias); nodeTypes.sort(); if (!(alias in aliasDescriptions)) { throw new Error( 'Missing alias descriptions of "' + alias + ", which covers " + nodeTypes.join(",") ); } readme.push("#### " + alias); readme.push(""); readme.push(aliasDescriptions[alias]); readme.push("```javascript"); readme.push("t.is" + alias + "(node);"); readme.push("```"); readme.push(""); readme.push("Covered nodes: "); for (const nodeType of nodeTypes) { readme.push("- [`" + nodeType + "`](#" + nodeType.toLowerCase() + ")"); } readme.push(""); } process.stdout.write(readme.join("\n"));