From 8270903ba25cd6a822c9c1ffc5ba96ec7b93076b Mon Sep 17 00:00:00 2001 From: Daniel Tschinder Date: Sat, 2 Dec 2017 12:20:10 +0100 Subject: [PATCH] Refactor @babel/types to be 100% ES-module (#6741) This generates the dynamic functions at buildtime and also splits the package into smaller files to avoid dependency circles. --- Makefile | 3 + .../scripts/generateTypeHelpers.js | 31 + .../scripts/generators/generateAsserts.js | 43 + .../scripts/generators/generateBuilders.js | 28 + .../scripts/generators/generateConstants.js | 17 + .../scripts/generators/generateValidators.js | 35 + .../babel-types/scripts/utils/formatCode.js | 9 + .../babel-types/scripts/utils/lowerFirst.js | 4 + .../babel-types/src/asserts/assertNode.js | 9 + .../src/asserts/generated/index.js | 1058 +++++++++++++++++ packages/babel-types/src/builders/builder.js | 34 + .../flow/createTypeAnnotationBasedOnTypeof.js | 34 + .../flow/createUnionTypeAnnotation.js | 19 + .../src/builders/generated/index.js | 839 +++++++++++++ .../src/builders/react/buildChildren.js | 27 + packages/babel-types/src/clone/clone.js | 16 + packages/babel-types/src/clone/cloneDeep.js | 28 + .../babel-types/src/clone/cloneWithoutLoc.js | 12 + .../babel-types/src/comments/addComment.js | 19 + .../babel-types/src/comments/addComments.js | 26 + .../src/comments/inheritInnerComments.js | 9 + .../src/comments/inheritLeadingComments.js | 9 + .../src/comments/inheritTrailingComments.js | 9 + .../src/comments/inheritsComments.js | 18 + .../src/comments/removeComments.js | 13 + .../src/constants/generated/index.js | 49 + .../src/{constants.js => constants/index.js} | 30 +- packages/babel-types/src/converters.js | 321 ----- .../babel-types/src/converters/ensureBlock.js | 15 + .../converters/gatherSequenceExpressions.js | 84 ++ .../src/converters/toBindingIdentifierName.js | 9 + .../babel-types/src/converters/toBlock.js | 36 + .../src/converters/toComputedKey.js | 12 + .../src/converters/toExpression.js | 39 + .../src/converters/toIdentifier.js | 23 + .../babel-types/src/converters/toKeyAlias.js | 41 + .../src/converters/toSequenceExpression.js | 28 + .../babel-types/src/converters/toStatement.js | 43 + .../babel-types/src/converters/valueToNode.js | 71 ++ packages/babel-types/src/definitions/core.js | 6 +- .../babel-types/src/definitions/es2015.js | 2 +- .../src/definitions/experimental.js | 2 +- packages/babel-types/src/definitions/flow.js | 2 +- packages/babel-types/src/definitions/index.js | 208 +--- packages/babel-types/src/definitions/init.js | 8 - packages/babel-types/src/definitions/jsx.js | 2 +- packages/babel-types/src/definitions/misc.js | 2 +- .../babel-types/src/definitions/typescript.js | 3 +- packages/babel-types/src/definitions/utils.js | 182 +++ packages/babel-types/src/index.js | 706 ++--------- .../modifications/appendToMemberExpression.js | 21 + .../flow/removeTypeDuplicates.js} | 62 +- .../babel-types/src/modifications/inherits.js | 31 + .../prependToMemberExpression.js | 14 + .../src/modifications/removeProperties.js | 31 + .../src/modifications/removePropertiesDeep.js | 12 + .../getBindingIdentifiers.js} | 35 +- .../retrievers/getOuterBindingIdentifiers.js | 9 + .../src/{ => traverse}/traverse.js | 48 +- .../babel-types/src/traverse/traverseFast.js | 32 + packages/babel-types/src/utils/inherit.js | 12 + .../react/cleanJSXElementLiteralChild.js} | 33 +- .../babel-types/src/utils/shallowEqual.js | 15 + packages/babel-types/src/validators.js | 316 ----- .../validators/buildMatchMemberExpression.js | 18 + .../src/validators/generated/index.js | 828 +++++++++++++ packages/babel-types/src/validators/is.js | 22 + .../babel-types/src/validators/isBinding.js | 21 + .../src/validators/isBlockScoped.js | 10 + .../babel-types/src/validators/isImmutable.js | 22 + packages/babel-types/src/validators/isLet.js | 13 + packages/babel-types/src/validators/isNode.js | 6 + .../src/validators/isNodesEquivalent.js | 50 + .../src/validators/isReferenced.js | 134 +++ .../babel-types/src/validators/isScope.js | 22 + .../src/validators/isSpecifierDefault.js | 14 + packages/babel-types/src/validators/isType.js | 24 + .../src/validators/isValidES3Identifier.js | 38 + .../src/validators/isValidIdentifier.js | 20 + packages/babel-types/src/validators/isVar.js | 12 + .../src/validators/matchesPattern.js | 45 + .../src/validators/react/isCompatTag.js | 4 + .../src/validators/react/isReactComponent.js | 6 + .../babel-types/src/validators/validate.js | 15 + 84 files changed, 4689 insertions(+), 1579 deletions(-) create mode 100644 packages/babel-types/scripts/generateTypeHelpers.js create mode 100644 packages/babel-types/scripts/generators/generateAsserts.js create mode 100644 packages/babel-types/scripts/generators/generateBuilders.js create mode 100644 packages/babel-types/scripts/generators/generateConstants.js create mode 100644 packages/babel-types/scripts/generators/generateValidators.js create mode 100644 packages/babel-types/scripts/utils/formatCode.js create mode 100644 packages/babel-types/scripts/utils/lowerFirst.js create mode 100644 packages/babel-types/src/asserts/assertNode.js create mode 100644 packages/babel-types/src/asserts/generated/index.js create mode 100644 packages/babel-types/src/builders/builder.js create mode 100644 packages/babel-types/src/builders/flow/createTypeAnnotationBasedOnTypeof.js create mode 100644 packages/babel-types/src/builders/flow/createUnionTypeAnnotation.js create mode 100644 packages/babel-types/src/builders/generated/index.js create mode 100644 packages/babel-types/src/builders/react/buildChildren.js create mode 100644 packages/babel-types/src/clone/clone.js create mode 100644 packages/babel-types/src/clone/cloneDeep.js create mode 100644 packages/babel-types/src/clone/cloneWithoutLoc.js create mode 100644 packages/babel-types/src/comments/addComment.js create mode 100644 packages/babel-types/src/comments/addComments.js create mode 100644 packages/babel-types/src/comments/inheritInnerComments.js create mode 100644 packages/babel-types/src/comments/inheritLeadingComments.js create mode 100644 packages/babel-types/src/comments/inheritTrailingComments.js create mode 100644 packages/babel-types/src/comments/inheritsComments.js create mode 100644 packages/babel-types/src/comments/removeComments.js create mode 100644 packages/babel-types/src/constants/generated/index.js rename packages/babel-types/src/{constants.js => constants/index.js} (80%) delete mode 100644 packages/babel-types/src/converters.js create mode 100644 packages/babel-types/src/converters/ensureBlock.js create mode 100644 packages/babel-types/src/converters/gatherSequenceExpressions.js create mode 100644 packages/babel-types/src/converters/toBindingIdentifierName.js create mode 100644 packages/babel-types/src/converters/toBlock.js create mode 100644 packages/babel-types/src/converters/toComputedKey.js create mode 100644 packages/babel-types/src/converters/toExpression.js create mode 100644 packages/babel-types/src/converters/toIdentifier.js create mode 100644 packages/babel-types/src/converters/toKeyAlias.js create mode 100644 packages/babel-types/src/converters/toSequenceExpression.js create mode 100644 packages/babel-types/src/converters/toStatement.js create mode 100644 packages/babel-types/src/converters/valueToNode.js delete mode 100644 packages/babel-types/src/definitions/init.js create mode 100644 packages/babel-types/src/definitions/utils.js create mode 100644 packages/babel-types/src/modifications/appendToMemberExpression.js rename packages/babel-types/src/{flow.js => modifications/flow/removeTypeDuplicates.js} (50%) create mode 100644 packages/babel-types/src/modifications/inherits.js create mode 100644 packages/babel-types/src/modifications/prependToMemberExpression.js create mode 100644 packages/babel-types/src/modifications/removeProperties.js create mode 100644 packages/babel-types/src/modifications/removePropertiesDeep.js rename packages/babel-types/src/{retrievers.js => retrievers/getBindingIdentifiers.js} (78%) create mode 100644 packages/babel-types/src/retrievers/getOuterBindingIdentifiers.js rename packages/babel-types/src/{ => traverse}/traverse.js (66%) create mode 100644 packages/babel-types/src/traverse/traverseFast.js create mode 100644 packages/babel-types/src/utils/inherit.js rename packages/babel-types/src/{react.js => utils/react/cleanJSXElementLiteralChild.js} (56%) create mode 100644 packages/babel-types/src/utils/shallowEqual.js delete mode 100644 packages/babel-types/src/validators.js create mode 100644 packages/babel-types/src/validators/buildMatchMemberExpression.js create mode 100644 packages/babel-types/src/validators/generated/index.js create mode 100644 packages/babel-types/src/validators/is.js create mode 100644 packages/babel-types/src/validators/isBinding.js create mode 100644 packages/babel-types/src/validators/isBlockScoped.js create mode 100644 packages/babel-types/src/validators/isImmutable.js create mode 100644 packages/babel-types/src/validators/isLet.js create mode 100644 packages/babel-types/src/validators/isNode.js create mode 100644 packages/babel-types/src/validators/isNodesEquivalent.js create mode 100644 packages/babel-types/src/validators/isReferenced.js create mode 100644 packages/babel-types/src/validators/isScope.js create mode 100644 packages/babel-types/src/validators/isSpecifierDefault.js create mode 100644 packages/babel-types/src/validators/isType.js create mode 100644 packages/babel-types/src/validators/isValidES3Identifier.js create mode 100644 packages/babel-types/src/validators/isValidIdentifier.js create mode 100644 packages/babel-types/src/validators/isVar.js create mode 100644 packages/babel-types/src/validators/matchesPattern.js create mode 100644 packages/babel-types/src/validators/react/isCompatTag.js create mode 100644 packages/babel-types/src/validators/react/isReactComponent.js create mode 100644 packages/babel-types/src/validators/validate.js diff --git a/Makefile b/Makefile index 8d07dae5fd..93e8734cf4 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,9 @@ build: clean # Build babylon before building all other projects make build-babylon ./node_modules/.bin/gulp build + node ./packages/babel-types/scripts/generateTypeHelpers.js + # call build again as the generated files might need to be compiled again. + ./node_modules/.bin/gulp build ifneq ("$(BABEL_ENV)", "cov") make build-standalone make build-preset-env-standalone diff --git a/packages/babel-types/scripts/generateTypeHelpers.js b/packages/babel-types/scripts/generateTypeHelpers.js new file mode 100644 index 0000000000..e122145c3c --- /dev/null +++ b/packages/babel-types/scripts/generateTypeHelpers.js @@ -0,0 +1,31 @@ +"use strict"; +const fs = require("fs"); +const path = require("path"); +const generateBuilders = require("./generators/generateBuilders"); +const generateValidators = require("./generators/generateValidators"); +const generateAsserts = require("./generators/generateAsserts"); +const generateConstants = require("./generators/generateConstants"); +const format = require("./utils/formatCode"); + +const baseDir = path.join(__dirname, "../src"); + +function writeFile(content, location) { + const file = path.join(baseDir, location); + + try { + fs.mkdirSync(path.dirname(file)); + } catch (error) { + if (error.code !== "EEXIST") { + throw error; + } + } + + fs.writeFileSync(file, format(content, file)); +} + +console.log("Generating @babel/types dynamic functions"); + +writeFile(generateBuilders(), "builders/generated/index.js"); +writeFile(generateValidators(), "validators/generated/index.js"); +writeFile(generateAsserts(), "asserts/generated/index.js"); +writeFile(generateConstants(), "constants/generated/index.js"); diff --git a/packages/babel-types/scripts/generators/generateAsserts.js b/packages/babel-types/scripts/generators/generateAsserts.js new file mode 100644 index 0000000000..65adfc4b14 --- /dev/null +++ b/packages/babel-types/scripts/generators/generateAsserts.js @@ -0,0 +1,43 @@ +"use strict"; +const definitions = require("../../lib/definitions"); + +function addAssertHelper(type) { + return `export function assert${type}(node: Object, opts?: Object = {}): void { + assert("${type}", node, opts) } + `; +} + +module.exports = function generateAsserts() { + let output = `// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import is from "../../validators/is"; + +function assert(type: string, node: Object, opts?: Object): void { + if (!is(type, node, opts)) { + throw new Error( + \`Expected type "\${type}" with option \${JSON.stringify(opts)}\`, + ); + } +}\n\n`; + + Object.keys(definitions.VISITOR_KEYS).forEach(type => { + output += addAssertHelper(type); + }); + + Object.keys(definitions.FLIPPED_ALIAS_KEYS).forEach(type => { + output += addAssertHelper(type); + }); + + Object.keys(definitions.DEPRECATED_KEYS).forEach(type => { + const newType = definitions.DEPRECATED_KEYS[type]; + output += `export function assert${type}(node: Object, opts: Object): void { + console.trace("The node type ${type} has been renamed to ${newType}"); + assert("${type}", node, opts); +}\n`; + }); + + return output; +}; diff --git a/packages/babel-types/scripts/generators/generateBuilders.js b/packages/babel-types/scripts/generators/generateBuilders.js new file mode 100644 index 0000000000..dc1b616395 --- /dev/null +++ b/packages/babel-types/scripts/generators/generateBuilders.js @@ -0,0 +1,28 @@ +"use strict"; +const definitions = require("../../lib/definitions"); +const lowerFirst = require("../utils/lowerFirst"); + +module.exports = function generateBuilders() { + let output = `// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import builder from "../builder";\n\n`; + + Object.keys(definitions.BUILDER_KEYS).forEach(type => { + output += `export function ${type}(...args: Array): Object { return builder("${type}", ...args); } +export { ${type} as ${lowerFirst(type)} };\n`; + }); + + Object.keys(definitions.DEPRECATED_KEYS).forEach(type => { + const newType = definitions.DEPRECATED_KEYS[type]; + output += `export function ${type}(...args: Array): Object { + console.trace("The node type ${type} has been renamed to ${newType}"); + return ${type}("${type}", ...args); +} +export { ${type} as ${lowerFirst(type)} };\n`; + }); + + return output; +}; diff --git a/packages/babel-types/scripts/generators/generateConstants.js b/packages/babel-types/scripts/generators/generateConstants.js new file mode 100644 index 0000000000..1e4d2cabae --- /dev/null +++ b/packages/babel-types/scripts/generators/generateConstants.js @@ -0,0 +1,17 @@ +"use strict"; +const definitions = require("../../lib/definitions"); + +module.exports = function generateConstants() { + let output = `// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import { FLIPPED_ALIAS_KEYS } from "../../definitions";\n\n`; + + Object.keys(definitions.FLIPPED_ALIAS_KEYS).forEach(type => { + output += `export const ${type.toUpperCase()}_TYPES = FLIPPED_ALIAS_KEYS["${type}"];\n`; + }); + + return output; +}; diff --git a/packages/babel-types/scripts/generators/generateValidators.js b/packages/babel-types/scripts/generators/generateValidators.js new file mode 100644 index 0000000000..b523d6adc8 --- /dev/null +++ b/packages/babel-types/scripts/generators/generateValidators.js @@ -0,0 +1,35 @@ +"use strict"; +const definitions = require("../../lib/definitions"); + +function addIsHelper(type) { + return `export function is${type}(node: Object, opts?: Object): boolean { + return is("${type}", node, opts) } + `; +} + +module.exports = function generateValidators() { + let output = `// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import is from "../is";\n\n`; + + Object.keys(definitions.VISITOR_KEYS).forEach(type => { + output += addIsHelper(type); + }); + + Object.keys(definitions.FLIPPED_ALIAS_KEYS).forEach(type => { + output += addIsHelper(type); + }); + + Object.keys(definitions.DEPRECATED_KEYS).forEach(type => { + const newType = definitions.DEPRECATED_KEYS[type]; + output += `export function is${type}(node: Object, opts: Object): boolean { + console.trace("The node type ${type} has been renamed to ${newType}"); + return is("${type}", node, opts); +}\n`; + }); + + return output; +}; diff --git a/packages/babel-types/scripts/utils/formatCode.js b/packages/babel-types/scripts/utils/formatCode.js new file mode 100644 index 0000000000..9d279e6e49 --- /dev/null +++ b/packages/babel-types/scripts/utils/formatCode.js @@ -0,0 +1,9 @@ +"use strict"; +const prettier = require("prettier"); + +module.exports = function formatCode(code, filename) { + filename = filename || __filename; + const prettierConfig = prettier.resolveConfig.sync(filename); + + return prettier.format(code, prettierConfig); +}; diff --git a/packages/babel-types/scripts/utils/lowerFirst.js b/packages/babel-types/scripts/utils/lowerFirst.js new file mode 100644 index 0000000000..9e7b0cee51 --- /dev/null +++ b/packages/babel-types/scripts/utils/lowerFirst.js @@ -0,0 +1,4 @@ +"use strict"; +module.exports = function lowerFirst(string) { + return string[0].toLowerCase() + string.slice(1); +}; diff --git a/packages/babel-types/src/asserts/assertNode.js b/packages/babel-types/src/asserts/assertNode.js new file mode 100644 index 0000000000..61891e54de --- /dev/null +++ b/packages/babel-types/src/asserts/assertNode.js @@ -0,0 +1,9 @@ +// @flow +import isNode from "../validators/isNode"; + +export default function assertNode(node?: Object): void { + if (!isNode(node)) { + const type = (node && node.type) || JSON.stringify(node); + throw new TypeError(`Not a valid node of type "${type}"`); + } +} diff --git a/packages/babel-types/src/asserts/generated/index.js b/packages/babel-types/src/asserts/generated/index.js new file mode 100644 index 0000000000..d0955c6aa0 --- /dev/null +++ b/packages/babel-types/src/asserts/generated/index.js @@ -0,0 +1,1058 @@ +// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import is from "../../validators/is"; + +function assert(type: string, node: Object, opts?: Object): void { + if (!is(type, node, opts)) { + throw new Error( + `Expected type "${type}" with option ${JSON.stringify(opts)}`, + ); + } +} + +export function assertArrayExpression(node: Object, opts?: Object = {}): void { + assert("ArrayExpression", node, opts); +} +export function assertAssignmentExpression( + node: Object, + opts?: Object = {}, +): void { + assert("AssignmentExpression", node, opts); +} +export function assertBinaryExpression(node: Object, opts?: Object = {}): void { + assert("BinaryExpression", node, opts); +} +export function assertDirective(node: Object, opts?: Object = {}): void { + assert("Directive", node, opts); +} +export function assertDirectiveLiteral(node: Object, opts?: Object = {}): void { + assert("DirectiveLiteral", node, opts); +} +export function assertBlockStatement(node: Object, opts?: Object = {}): void { + assert("BlockStatement", node, opts); +} +export function assertBreakStatement(node: Object, opts?: Object = {}): void { + assert("BreakStatement", node, opts); +} +export function assertCallExpression(node: Object, opts?: Object = {}): void { + assert("CallExpression", node, opts); +} +export function assertCatchClause(node: Object, opts?: Object = {}): void { + assert("CatchClause", node, opts); +} +export function assertConditionalExpression( + node: Object, + opts?: Object = {}, +): void { + assert("ConditionalExpression", node, opts); +} +export function assertContinueStatement( + node: Object, + opts?: Object = {}, +): void { + assert("ContinueStatement", node, opts); +} +export function assertDebuggerStatement( + node: Object, + opts?: Object = {}, +): void { + assert("DebuggerStatement", node, opts); +} +export function assertDoWhileStatement(node: Object, opts?: Object = {}): void { + assert("DoWhileStatement", node, opts); +} +export function assertEmptyStatement(node: Object, opts?: Object = {}): void { + assert("EmptyStatement", node, opts); +} +export function assertExpressionStatement( + node: Object, + opts?: Object = {}, +): void { + assert("ExpressionStatement", node, opts); +} +export function assertFile(node: Object, opts?: Object = {}): void { + assert("File", node, opts); +} +export function assertForInStatement(node: Object, opts?: Object = {}): void { + assert("ForInStatement", node, opts); +} +export function assertForStatement(node: Object, opts?: Object = {}): void { + assert("ForStatement", node, opts); +} +export function assertFunctionDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("FunctionDeclaration", node, opts); +} +export function assertFunctionExpression( + node: Object, + opts?: Object = {}, +): void { + assert("FunctionExpression", node, opts); +} +export function assertIdentifier(node: Object, opts?: Object = {}): void { + assert("Identifier", node, opts); +} +export function assertIfStatement(node: Object, opts?: Object = {}): void { + assert("IfStatement", node, opts); +} +export function assertLabeledStatement(node: Object, opts?: Object = {}): void { + assert("LabeledStatement", node, opts); +} +export function assertStringLiteral(node: Object, opts?: Object = {}): void { + assert("StringLiteral", node, opts); +} +export function assertNumericLiteral(node: Object, opts?: Object = {}): void { + assert("NumericLiteral", node, opts); +} +export function assertNullLiteral(node: Object, opts?: Object = {}): void { + assert("NullLiteral", node, opts); +} +export function assertBooleanLiteral(node: Object, opts?: Object = {}): void { + assert("BooleanLiteral", node, opts); +} +export function assertRegExpLiteral(node: Object, opts?: Object = {}): void { + assert("RegExpLiteral", node, opts); +} +export function assertLogicalExpression( + node: Object, + opts?: Object = {}, +): void { + assert("LogicalExpression", node, opts); +} +export function assertMemberExpression(node: Object, opts?: Object = {}): void { + assert("MemberExpression", node, opts); +} +export function assertNewExpression(node: Object, opts?: Object = {}): void { + assert("NewExpression", node, opts); +} +export function assertProgram(node: Object, opts?: Object = {}): void { + assert("Program", node, opts); +} +export function assertObjectExpression(node: Object, opts?: Object = {}): void { + assert("ObjectExpression", node, opts); +} +export function assertObjectMethod(node: Object, opts?: Object = {}): void { + assert("ObjectMethod", node, opts); +} +export function assertObjectProperty(node: Object, opts?: Object = {}): void { + assert("ObjectProperty", node, opts); +} +export function assertRestElement(node: Object, opts?: Object = {}): void { + assert("RestElement", node, opts); +} +export function assertReturnStatement(node: Object, opts?: Object = {}): void { + assert("ReturnStatement", node, opts); +} +export function assertSequenceExpression( + node: Object, + opts?: Object = {}, +): void { + assert("SequenceExpression", node, opts); +} +export function assertSwitchCase(node: Object, opts?: Object = {}): void { + assert("SwitchCase", node, opts); +} +export function assertSwitchStatement(node: Object, opts?: Object = {}): void { + assert("SwitchStatement", node, opts); +} +export function assertThisExpression(node: Object, opts?: Object = {}): void { + assert("ThisExpression", node, opts); +} +export function assertThrowStatement(node: Object, opts?: Object = {}): void { + assert("ThrowStatement", node, opts); +} +export function assertTryStatement(node: Object, opts?: Object = {}): void { + assert("TryStatement", node, opts); +} +export function assertUnaryExpression(node: Object, opts?: Object = {}): void { + assert("UnaryExpression", node, opts); +} +export function assertUpdateExpression(node: Object, opts?: Object = {}): void { + assert("UpdateExpression", node, opts); +} +export function assertVariableDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("VariableDeclaration", node, opts); +} +export function assertVariableDeclarator( + node: Object, + opts?: Object = {}, +): void { + assert("VariableDeclarator", node, opts); +} +export function assertWhileStatement(node: Object, opts?: Object = {}): void { + assert("WhileStatement", node, opts); +} +export function assertWithStatement(node: Object, opts?: Object = {}): void { + assert("WithStatement", node, opts); +} +export function assertAssignmentPattern( + node: Object, + opts?: Object = {}, +): void { + assert("AssignmentPattern", node, opts); +} +export function assertArrayPattern(node: Object, opts?: Object = {}): void { + assert("ArrayPattern", node, opts); +} +export function assertArrowFunctionExpression( + node: Object, + opts?: Object = {}, +): void { + assert("ArrowFunctionExpression", node, opts); +} +export function assertClassBody(node: Object, opts?: Object = {}): void { + assert("ClassBody", node, opts); +} +export function assertClassDeclaration(node: Object, opts?: Object = {}): void { + assert("ClassDeclaration", node, opts); +} +export function assertClassExpression(node: Object, opts?: Object = {}): void { + assert("ClassExpression", node, opts); +} +export function assertExportAllDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("ExportAllDeclaration", node, opts); +} +export function assertExportDefaultDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("ExportDefaultDeclaration", node, opts); +} +export function assertExportNamedDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("ExportNamedDeclaration", node, opts); +} +export function assertExportSpecifier(node: Object, opts?: Object = {}): void { + assert("ExportSpecifier", node, opts); +} +export function assertForOfStatement(node: Object, opts?: Object = {}): void { + assert("ForOfStatement", node, opts); +} +export function assertImportDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("ImportDeclaration", node, opts); +} +export function assertImportDefaultSpecifier( + node: Object, + opts?: Object = {}, +): void { + assert("ImportDefaultSpecifier", node, opts); +} +export function assertImportNamespaceSpecifier( + node: Object, + opts?: Object = {}, +): void { + assert("ImportNamespaceSpecifier", node, opts); +} +export function assertImportSpecifier(node: Object, opts?: Object = {}): void { + assert("ImportSpecifier", node, opts); +} +export function assertMetaProperty(node: Object, opts?: Object = {}): void { + assert("MetaProperty", node, opts); +} +export function assertClassMethod(node: Object, opts?: Object = {}): void { + assert("ClassMethod", node, opts); +} +export function assertObjectPattern(node: Object, opts?: Object = {}): void { + assert("ObjectPattern", node, opts); +} +export function assertSpreadElement(node: Object, opts?: Object = {}): void { + assert("SpreadElement", node, opts); +} +export function assertSuper(node: Object, opts?: Object = {}): void { + assert("Super", node, opts); +} +export function assertTaggedTemplateExpression( + node: Object, + opts?: Object = {}, +): void { + assert("TaggedTemplateExpression", node, opts); +} +export function assertTemplateElement(node: Object, opts?: Object = {}): void { + assert("TemplateElement", node, opts); +} +export function assertTemplateLiteral(node: Object, opts?: Object = {}): void { + assert("TemplateLiteral", node, opts); +} +export function assertYieldExpression(node: Object, opts?: Object = {}): void { + assert("YieldExpression", node, opts); +} +export function assertAnyTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("AnyTypeAnnotation", node, opts); +} +export function assertArrayTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("ArrayTypeAnnotation", node, opts); +} +export function assertBooleanTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("BooleanTypeAnnotation", node, opts); +} +export function assertBooleanLiteralTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("BooleanLiteralTypeAnnotation", node, opts); +} +export function assertNullLiteralTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("NullLiteralTypeAnnotation", node, opts); +} +export function assertClassImplements(node: Object, opts?: Object = {}): void { + assert("ClassImplements", node, opts); +} +export function assertDeclareClass(node: Object, opts?: Object = {}): void { + assert("DeclareClass", node, opts); +} +export function assertDeclareFunction(node: Object, opts?: Object = {}): void { + assert("DeclareFunction", node, opts); +} +export function assertDeclareInterface(node: Object, opts?: Object = {}): void { + assert("DeclareInterface", node, opts); +} +export function assertDeclareModule(node: Object, opts?: Object = {}): void { + assert("DeclareModule", node, opts); +} +export function assertDeclareModuleExports( + node: Object, + opts?: Object = {}, +): void { + assert("DeclareModuleExports", node, opts); +} +export function assertDeclareTypeAlias(node: Object, opts?: Object = {}): void { + assert("DeclareTypeAlias", node, opts); +} +export function assertDeclareOpaqueType( + node: Object, + opts?: Object = {}, +): void { + assert("DeclareOpaqueType", node, opts); +} +export function assertDeclareVariable(node: Object, opts?: Object = {}): void { + assert("DeclareVariable", node, opts); +} +export function assertDeclareExportDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("DeclareExportDeclaration", node, opts); +} +export function assertDeclareExportAllDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("DeclareExportAllDeclaration", node, opts); +} +export function assertDeclaredPredicate( + node: Object, + opts?: Object = {}, +): void { + assert("DeclaredPredicate", node, opts); +} +export function assertExistsTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("ExistsTypeAnnotation", node, opts); +} +export function assertFunctionTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("FunctionTypeAnnotation", node, opts); +} +export function assertFunctionTypeParam( + node: Object, + opts?: Object = {}, +): void { + assert("FunctionTypeParam", node, opts); +} +export function assertGenericTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("GenericTypeAnnotation", node, opts); +} +export function assertInferredPredicate( + node: Object, + opts?: Object = {}, +): void { + assert("InferredPredicate", node, opts); +} +export function assertInterfaceExtends(node: Object, opts?: Object = {}): void { + assert("InterfaceExtends", node, opts); +} +export function assertInterfaceDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("InterfaceDeclaration", node, opts); +} +export function assertIntersectionTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("IntersectionTypeAnnotation", node, opts); +} +export function assertMixedTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("MixedTypeAnnotation", node, opts); +} +export function assertEmptyTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("EmptyTypeAnnotation", node, opts); +} +export function assertNullableTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("NullableTypeAnnotation", node, opts); +} +export function assertNumberLiteralTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("NumberLiteralTypeAnnotation", node, opts); +} +export function assertNumberTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("NumberTypeAnnotation", node, opts); +} +export function assertObjectTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("ObjectTypeAnnotation", node, opts); +} +export function assertObjectTypeCallProperty( + node: Object, + opts?: Object = {}, +): void { + assert("ObjectTypeCallProperty", node, opts); +} +export function assertObjectTypeIndexer( + node: Object, + opts?: Object = {}, +): void { + assert("ObjectTypeIndexer", node, opts); +} +export function assertObjectTypeProperty( + node: Object, + opts?: Object = {}, +): void { + assert("ObjectTypeProperty", node, opts); +} +export function assertObjectTypeSpreadProperty( + node: Object, + opts?: Object = {}, +): void { + assert("ObjectTypeSpreadProperty", node, opts); +} +export function assertOpaqueType(node: Object, opts?: Object = {}): void { + assert("OpaqueType", node, opts); +} +export function assertQualifiedTypeIdentifier( + node: Object, + opts?: Object = {}, +): void { + assert("QualifiedTypeIdentifier", node, opts); +} +export function assertStringLiteralTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("StringLiteralTypeAnnotation", node, opts); +} +export function assertStringTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("StringTypeAnnotation", node, opts); +} +export function assertThisTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("ThisTypeAnnotation", node, opts); +} +export function assertTupleTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("TupleTypeAnnotation", node, opts); +} +export function assertTypeofTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("TypeofTypeAnnotation", node, opts); +} +export function assertTypeAlias(node: Object, opts?: Object = {}): void { + assert("TypeAlias", node, opts); +} +export function assertTypeAnnotation(node: Object, opts?: Object = {}): void { + assert("TypeAnnotation", node, opts); +} +export function assertTypeCastExpression( + node: Object, + opts?: Object = {}, +): void { + assert("TypeCastExpression", node, opts); +} +export function assertTypeParameter(node: Object, opts?: Object = {}): void { + assert("TypeParameter", node, opts); +} +export function assertTypeParameterDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TypeParameterDeclaration", node, opts); +} +export function assertTypeParameterInstantiation( + node: Object, + opts?: Object = {}, +): void { + assert("TypeParameterInstantiation", node, opts); +} +export function assertUnionTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("UnionTypeAnnotation", node, opts); +} +export function assertVoidTypeAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("VoidTypeAnnotation", node, opts); +} +export function assertJSXAttribute(node: Object, opts?: Object = {}): void { + assert("JSXAttribute", node, opts); +} +export function assertJSXClosingElement( + node: Object, + opts?: Object = {}, +): void { + assert("JSXClosingElement", node, opts); +} +export function assertJSXElement(node: Object, opts?: Object = {}): void { + assert("JSXElement", node, opts); +} +export function assertJSXEmptyExpression( + node: Object, + opts?: Object = {}, +): void { + assert("JSXEmptyExpression", node, opts); +} +export function assertJSXExpressionContainer( + node: Object, + opts?: Object = {}, +): void { + assert("JSXExpressionContainer", node, opts); +} +export function assertJSXSpreadChild(node: Object, opts?: Object = {}): void { + assert("JSXSpreadChild", node, opts); +} +export function assertJSXIdentifier(node: Object, opts?: Object = {}): void { + assert("JSXIdentifier", node, opts); +} +export function assertJSXMemberExpression( + node: Object, + opts?: Object = {}, +): void { + assert("JSXMemberExpression", node, opts); +} +export function assertJSXNamespacedName( + node: Object, + opts?: Object = {}, +): void { + assert("JSXNamespacedName", node, opts); +} +export function assertJSXOpeningElement( + node: Object, + opts?: Object = {}, +): void { + assert("JSXOpeningElement", node, opts); +} +export function assertJSXSpreadAttribute( + node: Object, + opts?: Object = {}, +): void { + assert("JSXSpreadAttribute", node, opts); +} +export function assertJSXText(node: Object, opts?: Object = {}): void { + assert("JSXText", node, opts); +} +export function assertJSXFragment(node: Object, opts?: Object = {}): void { + assert("JSXFragment", node, opts); +} +export function assertJSXOpeningFragment( + node: Object, + opts?: Object = {}, +): void { + assert("JSXOpeningFragment", node, opts); +} +export function assertJSXClosingFragment( + node: Object, + opts?: Object = {}, +): void { + assert("JSXClosingFragment", node, opts); +} +export function assertNoop(node: Object, opts?: Object = {}): void { + assert("Noop", node, opts); +} +export function assertParenthesizedExpression( + node: Object, + opts?: Object = {}, +): void { + assert("ParenthesizedExpression", node, opts); +} +export function assertAwaitExpression(node: Object, opts?: Object = {}): void { + assert("AwaitExpression", node, opts); +} +export function assertBindExpression(node: Object, opts?: Object = {}): void { + assert("BindExpression", node, opts); +} +export function assertClassProperty(node: Object, opts?: Object = {}): void { + assert("ClassProperty", node, opts); +} +export function assertImport(node: Object, opts?: Object = {}): void { + assert("Import", node, opts); +} +export function assertDecorator(node: Object, opts?: Object = {}): void { + assert("Decorator", node, opts); +} +export function assertDoExpression(node: Object, opts?: Object = {}): void { + assert("DoExpression", node, opts); +} +export function assertExportDefaultSpecifier( + node: Object, + opts?: Object = {}, +): void { + assert("ExportDefaultSpecifier", node, opts); +} +export function assertExportNamespaceSpecifier( + node: Object, + opts?: Object = {}, +): void { + assert("ExportNamespaceSpecifier", node, opts); +} +export function assertTSParameterProperty( + node: Object, + opts?: Object = {}, +): void { + assert("TSParameterProperty", node, opts); +} +export function assertTSDeclareFunction( + node: Object, + opts?: Object = {}, +): void { + assert("TSDeclareFunction", node, opts); +} +export function assertTSDeclareMethod(node: Object, opts?: Object = {}): void { + assert("TSDeclareMethod", node, opts); +} +export function assertTSQualifiedName(node: Object, opts?: Object = {}): void { + assert("TSQualifiedName", node, opts); +} +export function assertTSCallSignatureDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSCallSignatureDeclaration", node, opts); +} +export function assertTSConstructSignatureDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSConstructSignatureDeclaration", node, opts); +} +export function assertTSPropertySignature( + node: Object, + opts?: Object = {}, +): void { + assert("TSPropertySignature", node, opts); +} +export function assertTSMethodSignature( + node: Object, + opts?: Object = {}, +): void { + assert("TSMethodSignature", node, opts); +} +export function assertTSIndexSignature(node: Object, opts?: Object = {}): void { + assert("TSIndexSignature", node, opts); +} +export function assertTSAnyKeyword(node: Object, opts?: Object = {}): void { + assert("TSAnyKeyword", node, opts); +} +export function assertTSNumberKeyword(node: Object, opts?: Object = {}): void { + assert("TSNumberKeyword", node, opts); +} +export function assertTSObjectKeyword(node: Object, opts?: Object = {}): void { + assert("TSObjectKeyword", node, opts); +} +export function assertTSBooleanKeyword(node: Object, opts?: Object = {}): void { + assert("TSBooleanKeyword", node, opts); +} +export function assertTSStringKeyword(node: Object, opts?: Object = {}): void { + assert("TSStringKeyword", node, opts); +} +export function assertTSSymbolKeyword(node: Object, opts?: Object = {}): void { + assert("TSSymbolKeyword", node, opts); +} +export function assertTSVoidKeyword(node: Object, opts?: Object = {}): void { + assert("TSVoidKeyword", node, opts); +} +export function assertTSUndefinedKeyword( + node: Object, + opts?: Object = {}, +): void { + assert("TSUndefinedKeyword", node, opts); +} +export function assertTSNullKeyword(node: Object, opts?: Object = {}): void { + assert("TSNullKeyword", node, opts); +} +export function assertTSNeverKeyword(node: Object, opts?: Object = {}): void { + assert("TSNeverKeyword", node, opts); +} +export function assertTSThisType(node: Object, opts?: Object = {}): void { + assert("TSThisType", node, opts); +} +export function assertTSFunctionType(node: Object, opts?: Object = {}): void { + assert("TSFunctionType", node, opts); +} +export function assertTSConstructorType( + node: Object, + opts?: Object = {}, +): void { + assert("TSConstructorType", node, opts); +} +export function assertTSTypeReference(node: Object, opts?: Object = {}): void { + assert("TSTypeReference", node, opts); +} +export function assertTSTypePredicate(node: Object, opts?: Object = {}): void { + assert("TSTypePredicate", node, opts); +} +export function assertTSTypeQuery(node: Object, opts?: Object = {}): void { + assert("TSTypeQuery", node, opts); +} +export function assertTSTypeLiteral(node: Object, opts?: Object = {}): void { + assert("TSTypeLiteral", node, opts); +} +export function assertTSArrayType(node: Object, opts?: Object = {}): void { + assert("TSArrayType", node, opts); +} +export function assertTSTupleType(node: Object, opts?: Object = {}): void { + assert("TSTupleType", node, opts); +} +export function assertTSUnionType(node: Object, opts?: Object = {}): void { + assert("TSUnionType", node, opts); +} +export function assertTSIntersectionType( + node: Object, + opts?: Object = {}, +): void { + assert("TSIntersectionType", node, opts); +} +export function assertTSParenthesizedType( + node: Object, + opts?: Object = {}, +): void { + assert("TSParenthesizedType", node, opts); +} +export function assertTSTypeOperator(node: Object, opts?: Object = {}): void { + assert("TSTypeOperator", node, opts); +} +export function assertTSIndexedAccessType( + node: Object, + opts?: Object = {}, +): void { + assert("TSIndexedAccessType", node, opts); +} +export function assertTSMappedType(node: Object, opts?: Object = {}): void { + assert("TSMappedType", node, opts); +} +export function assertTSLiteralType(node: Object, opts?: Object = {}): void { + assert("TSLiteralType", node, opts); +} +export function assertTSExpressionWithTypeArguments( + node: Object, + opts?: Object = {}, +): void { + assert("TSExpressionWithTypeArguments", node, opts); +} +export function assertTSInterfaceDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSInterfaceDeclaration", node, opts); +} +export function assertTSInterfaceBody(node: Object, opts?: Object = {}): void { + assert("TSInterfaceBody", node, opts); +} +export function assertTSTypeAliasDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSTypeAliasDeclaration", node, opts); +} +export function assertTSAsExpression(node: Object, opts?: Object = {}): void { + assert("TSAsExpression", node, opts); +} +export function assertTSTypeAssertion(node: Object, opts?: Object = {}): void { + assert("TSTypeAssertion", node, opts); +} +export function assertTSEnumDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSEnumDeclaration", node, opts); +} +export function assertTSEnumMember(node: Object, opts?: Object = {}): void { + assert("TSEnumMember", node, opts); +} +export function assertTSModuleDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSModuleDeclaration", node, opts); +} +export function assertTSModuleBlock(node: Object, opts?: Object = {}): void { + assert("TSModuleBlock", node, opts); +} +export function assertTSImportEqualsDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSImportEqualsDeclaration", node, opts); +} +export function assertTSExternalModuleReference( + node: Object, + opts?: Object = {}, +): void { + assert("TSExternalModuleReference", node, opts); +} +export function assertTSNonNullExpression( + node: Object, + opts?: Object = {}, +): void { + assert("TSNonNullExpression", node, opts); +} +export function assertTSExportAssignment( + node: Object, + opts?: Object = {}, +): void { + assert("TSExportAssignment", node, opts); +} +export function assertTSNamespaceExportDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSNamespaceExportDeclaration", node, opts); +} +export function assertTSTypeAnnotation(node: Object, opts?: Object = {}): void { + assert("TSTypeAnnotation", node, opts); +} +export function assertTSTypeParameterInstantiation( + node: Object, + opts?: Object = {}, +): void { + assert("TSTypeParameterInstantiation", node, opts); +} +export function assertTSTypeParameterDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("TSTypeParameterDeclaration", node, opts); +} +export function assertTSTypeParameter(node: Object, opts?: Object = {}): void { + assert("TSTypeParameter", node, opts); +} +export function assertExpression(node: Object, opts?: Object = {}): void { + assert("Expression", node, opts); +} +export function assertBinary(node: Object, opts?: Object = {}): void { + assert("Binary", node, opts); +} +export function assertScopable(node: Object, opts?: Object = {}): void { + assert("Scopable", node, opts); +} +export function assertBlockParent(node: Object, opts?: Object = {}): void { + assert("BlockParent", node, opts); +} +export function assertBlock(node: Object, opts?: Object = {}): void { + assert("Block", node, opts); +} +export function assertStatement(node: Object, opts?: Object = {}): void { + assert("Statement", node, opts); +} +export function assertTerminatorless(node: Object, opts?: Object = {}): void { + assert("Terminatorless", node, opts); +} +export function assertCompletionStatement( + node: Object, + opts?: Object = {}, +): void { + assert("CompletionStatement", node, opts); +} +export function assertConditional(node: Object, opts?: Object = {}): void { + assert("Conditional", node, opts); +} +export function assertLoop(node: Object, opts?: Object = {}): void { + assert("Loop", node, opts); +} +export function assertWhile(node: Object, opts?: Object = {}): void { + assert("While", node, opts); +} +export function assertExpressionWrapper( + node: Object, + opts?: Object = {}, +): void { + assert("ExpressionWrapper", node, opts); +} +export function assertFor(node: Object, opts?: Object = {}): void { + assert("For", node, opts); +} +export function assertForXStatement(node: Object, opts?: Object = {}): void { + assert("ForXStatement", node, opts); +} +export function assertFunction(node: Object, opts?: Object = {}): void { + assert("Function", node, opts); +} +export function assertFunctionParent(node: Object, opts?: Object = {}): void { + assert("FunctionParent", node, opts); +} +export function assertPureish(node: Object, opts?: Object = {}): void { + assert("Pureish", node, opts); +} +export function assertDeclaration(node: Object, opts?: Object = {}): void { + assert("Declaration", node, opts); +} +export function assertPatternLike(node: Object, opts?: Object = {}): void { + assert("PatternLike", node, opts); +} +export function assertLVal(node: Object, opts?: Object = {}): void { + assert("LVal", node, opts); +} +export function assertTSEntityName(node: Object, opts?: Object = {}): void { + assert("TSEntityName", node, opts); +} +export function assertLiteral(node: Object, opts?: Object = {}): void { + assert("Literal", node, opts); +} +export function assertImmutable(node: Object, opts?: Object = {}): void { + assert("Immutable", node, opts); +} +export function assertUserWhitespacable( + node: Object, + opts?: Object = {}, +): void { + assert("UserWhitespacable", node, opts); +} +export function assertMethod(node: Object, opts?: Object = {}): void { + assert("Method", node, opts); +} +export function assertObjectMember(node: Object, opts?: Object = {}): void { + assert("ObjectMember", node, opts); +} +export function assertProperty(node: Object, opts?: Object = {}): void { + assert("Property", node, opts); +} +export function assertUnaryLike(node: Object, opts?: Object = {}): void { + assert("UnaryLike", node, opts); +} +export function assertPattern(node: Object, opts?: Object = {}): void { + assert("Pattern", node, opts); +} +export function assertClass(node: Object, opts?: Object = {}): void { + assert("Class", node, opts); +} +export function assertModuleDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("ModuleDeclaration", node, opts); +} +export function assertExportDeclaration( + node: Object, + opts?: Object = {}, +): void { + assert("ExportDeclaration", node, opts); +} +export function assertModuleSpecifier(node: Object, opts?: Object = {}): void { + assert("ModuleSpecifier", node, opts); +} +export function assertFlow(node: Object, opts?: Object = {}): void { + assert("Flow", node, opts); +} +export function assertFlowBaseAnnotation( + node: Object, + opts?: Object = {}, +): void { + assert("FlowBaseAnnotation", node, opts); +} +export function assertFlowDeclaration(node: Object, opts?: Object = {}): void { + assert("FlowDeclaration", node, opts); +} +export function assertFlowPredicate(node: Object, opts?: Object = {}): void { + assert("FlowPredicate", node, opts); +} +export function assertJSX(node: Object, opts?: Object = {}): void { + assert("JSX", node, opts); +} +export function assertTSTypeElement(node: Object, opts?: Object = {}): void { + assert("TSTypeElement", node, opts); +} +export function assertTSType(node: Object, opts?: Object = {}): void { + assert("TSType", node, opts); +} +export function assertNumberLiteral(node: Object, opts: Object): void { + console.trace( + "The node type NumberLiteral has been renamed to NumericLiteral", + ); + assert("NumberLiteral", node, opts); +} +export function assertRegexLiteral(node: Object, opts: Object): void { + console.trace("The node type RegexLiteral has been renamed to RegExpLiteral"); + assert("RegexLiteral", node, opts); +} +export function assertRestProperty(node: Object, opts: Object): void { + console.trace("The node type RestProperty has been renamed to RestElement"); + assert("RestProperty", node, opts); +} +export function assertSpreadProperty(node: Object, opts: Object): void { + console.trace( + "The node type SpreadProperty has been renamed to SpreadElement", + ); + assert("SpreadProperty", node, opts); +} diff --git a/packages/babel-types/src/builders/builder.js b/packages/babel-types/src/builders/builder.js new file mode 100644 index 0000000000..45c30c2f26 --- /dev/null +++ b/packages/babel-types/src/builders/builder.js @@ -0,0 +1,34 @@ +// @flow +import loClone from "lodash/clone"; +import { NODE_FIELDS, BUILDER_KEYS } from "../definitions"; +import validate from "../validators/validate"; + +export default function builder(type: string, ...args: Array): Object { + const keys = BUILDER_KEYS[type]; + const countArgs = args.length; + if (countArgs > keys.length) { + throw new Error( + `${type}: Too many arguments passed. Received ${countArgs} but can receive no more than ${keys.length}`, + ); + } + + const node = { type }; + + let i = 0; + keys.forEach(key => { + const field = NODE_FIELDS[type][key]; + + let arg; + if (i < countArgs) arg = args[i]; + if (arg === undefined) arg = loClone(field.default); + + node[key] = arg; + i++; + }); + + for (const key in node) { + validate(node, key, node[key]); + } + + return node; +} diff --git a/packages/babel-types/src/builders/flow/createTypeAnnotationBasedOnTypeof.js b/packages/babel-types/src/builders/flow/createTypeAnnotationBasedOnTypeof.js new file mode 100644 index 0000000000..57f930abcb --- /dev/null +++ b/packages/babel-types/src/builders/flow/createTypeAnnotationBasedOnTypeof.js @@ -0,0 +1,34 @@ +// @flow +import { + stringTypeAnnotation, + numberTypeAnnotation, + voidTypeAnnotation, + booleanTypeAnnotation, + genericTypeAnnotation, + identifier, +} from "../generated"; + +/** + * Create a type annotation based on typeof expression. + */ +export default function createTypeAnnotationBasedOnTypeof( + type: string, +): Object { + if (type === "string") { + return stringTypeAnnotation(); + } else if (type === "number") { + return numberTypeAnnotation(); + } else if (type === "undefined") { + return voidTypeAnnotation(); + } else if (type === "boolean") { + return booleanTypeAnnotation(); + } else if (type === "function") { + return genericTypeAnnotation(identifier("Function")); + } else if (type === "object") { + return genericTypeAnnotation(identifier("Object")); + } else if (type === "symbol") { + return genericTypeAnnotation(identifier("Symbol")); + } else { + throw new Error("Invalid typeof value"); + } +} diff --git a/packages/babel-types/src/builders/flow/createUnionTypeAnnotation.js b/packages/babel-types/src/builders/flow/createUnionTypeAnnotation.js new file mode 100644 index 0000000000..4b181dab0c --- /dev/null +++ b/packages/babel-types/src/builders/flow/createUnionTypeAnnotation.js @@ -0,0 +1,19 @@ +// @flow +import { unionTypeAnnotation } from "../generated"; +import removeTypeDuplicates from "../../modifications/flow/removeTypeDuplicates"; + +/** + * Takes an array of `types` and flattens them, removing duplicates and + * returns a `UnionTypeAnnotation` node containg them. + */ +export default function createUnionTypeAnnotation( + types: Array, +): Object { + const flattened = removeTypeDuplicates(types); + + if (flattened.length === 1) { + return flattened[0]; + } else { + return unionTypeAnnotation(flattened); + } +} diff --git a/packages/babel-types/src/builders/generated/index.js b/packages/babel-types/src/builders/generated/index.js new file mode 100644 index 0000000000..c0c210401c --- /dev/null +++ b/packages/babel-types/src/builders/generated/index.js @@ -0,0 +1,839 @@ +// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import builder from "../builder"; + +export function ArrayExpression(...args: Array): Object { + return builder("ArrayExpression", ...args); +} +export { ArrayExpression as arrayExpression }; +export function AssignmentExpression(...args: Array): Object { + return builder("AssignmentExpression", ...args); +} +export { AssignmentExpression as assignmentExpression }; +export function BinaryExpression(...args: Array): Object { + return builder("BinaryExpression", ...args); +} +export { BinaryExpression as binaryExpression }; +export function Directive(...args: Array): Object { + return builder("Directive", ...args); +} +export { Directive as directive }; +export function DirectiveLiteral(...args: Array): Object { + return builder("DirectiveLiteral", ...args); +} +export { DirectiveLiteral as directiveLiteral }; +export function BlockStatement(...args: Array): Object { + return builder("BlockStatement", ...args); +} +export { BlockStatement as blockStatement }; +export function BreakStatement(...args: Array): Object { + return builder("BreakStatement", ...args); +} +export { BreakStatement as breakStatement }; +export function CallExpression(...args: Array): Object { + return builder("CallExpression", ...args); +} +export { CallExpression as callExpression }; +export function CatchClause(...args: Array): Object { + return builder("CatchClause", ...args); +} +export { CatchClause as catchClause }; +export function ConditionalExpression(...args: Array): Object { + return builder("ConditionalExpression", ...args); +} +export { ConditionalExpression as conditionalExpression }; +export function ContinueStatement(...args: Array): Object { + return builder("ContinueStatement", ...args); +} +export { ContinueStatement as continueStatement }; +export function DebuggerStatement(...args: Array): Object { + return builder("DebuggerStatement", ...args); +} +export { DebuggerStatement as debuggerStatement }; +export function DoWhileStatement(...args: Array): Object { + return builder("DoWhileStatement", ...args); +} +export { DoWhileStatement as doWhileStatement }; +export function EmptyStatement(...args: Array): Object { + return builder("EmptyStatement", ...args); +} +export { EmptyStatement as emptyStatement }; +export function ExpressionStatement(...args: Array): Object { + return builder("ExpressionStatement", ...args); +} +export { ExpressionStatement as expressionStatement }; +export function File(...args: Array): Object { + return builder("File", ...args); +} +export { File as file }; +export function ForInStatement(...args: Array): Object { + return builder("ForInStatement", ...args); +} +export { ForInStatement as forInStatement }; +export function ForStatement(...args: Array): Object { + return builder("ForStatement", ...args); +} +export { ForStatement as forStatement }; +export function FunctionDeclaration(...args: Array): Object { + return builder("FunctionDeclaration", ...args); +} +export { FunctionDeclaration as functionDeclaration }; +export function FunctionExpression(...args: Array): Object { + return builder("FunctionExpression", ...args); +} +export { FunctionExpression as functionExpression }; +export function Identifier(...args: Array): Object { + return builder("Identifier", ...args); +} +export { Identifier as identifier }; +export function IfStatement(...args: Array): Object { + return builder("IfStatement", ...args); +} +export { IfStatement as ifStatement }; +export function LabeledStatement(...args: Array): Object { + return builder("LabeledStatement", ...args); +} +export { LabeledStatement as labeledStatement }; +export function StringLiteral(...args: Array): Object { + return builder("StringLiteral", ...args); +} +export { StringLiteral as stringLiteral }; +export function NumericLiteral(...args: Array): Object { + return builder("NumericLiteral", ...args); +} +export { NumericLiteral as numericLiteral }; +export function NullLiteral(...args: Array): Object { + return builder("NullLiteral", ...args); +} +export { NullLiteral as nullLiteral }; +export function BooleanLiteral(...args: Array): Object { + return builder("BooleanLiteral", ...args); +} +export { BooleanLiteral as booleanLiteral }; +export function RegExpLiteral(...args: Array): Object { + return builder("RegExpLiteral", ...args); +} +export { RegExpLiteral as regExpLiteral }; +export function LogicalExpression(...args: Array): Object { + return builder("LogicalExpression", ...args); +} +export { LogicalExpression as logicalExpression }; +export function MemberExpression(...args: Array): Object { + return builder("MemberExpression", ...args); +} +export { MemberExpression as memberExpression }; +export function NewExpression(...args: Array): Object { + return builder("NewExpression", ...args); +} +export { NewExpression as newExpression }; +export function Program(...args: Array): Object { + return builder("Program", ...args); +} +export { Program as program }; +export function ObjectExpression(...args: Array): Object { + return builder("ObjectExpression", ...args); +} +export { ObjectExpression as objectExpression }; +export function ObjectMethod(...args: Array): Object { + return builder("ObjectMethod", ...args); +} +export { ObjectMethod as objectMethod }; +export function ObjectProperty(...args: Array): Object { + return builder("ObjectProperty", ...args); +} +export { ObjectProperty as objectProperty }; +export function RestElement(...args: Array): Object { + return builder("RestElement", ...args); +} +export { RestElement as restElement }; +export function ReturnStatement(...args: Array): Object { + return builder("ReturnStatement", ...args); +} +export { ReturnStatement as returnStatement }; +export function SequenceExpression(...args: Array): Object { + return builder("SequenceExpression", ...args); +} +export { SequenceExpression as sequenceExpression }; +export function SwitchCase(...args: Array): Object { + return builder("SwitchCase", ...args); +} +export { SwitchCase as switchCase }; +export function SwitchStatement(...args: Array): Object { + return builder("SwitchStatement", ...args); +} +export { SwitchStatement as switchStatement }; +export function ThisExpression(...args: Array): Object { + return builder("ThisExpression", ...args); +} +export { ThisExpression as thisExpression }; +export function ThrowStatement(...args: Array): Object { + return builder("ThrowStatement", ...args); +} +export { ThrowStatement as throwStatement }; +export function TryStatement(...args: Array): Object { + return builder("TryStatement", ...args); +} +export { TryStatement as tryStatement }; +export function UnaryExpression(...args: Array): Object { + return builder("UnaryExpression", ...args); +} +export { UnaryExpression as unaryExpression }; +export function UpdateExpression(...args: Array): Object { + return builder("UpdateExpression", ...args); +} +export { UpdateExpression as updateExpression }; +export function VariableDeclaration(...args: Array): Object { + return builder("VariableDeclaration", ...args); +} +export { VariableDeclaration as variableDeclaration }; +export function VariableDeclarator(...args: Array): Object { + return builder("VariableDeclarator", ...args); +} +export { VariableDeclarator as variableDeclarator }; +export function WhileStatement(...args: Array): Object { + return builder("WhileStatement", ...args); +} +export { WhileStatement as whileStatement }; +export function WithStatement(...args: Array): Object { + return builder("WithStatement", ...args); +} +export { WithStatement as withStatement }; +export function AssignmentPattern(...args: Array): Object { + return builder("AssignmentPattern", ...args); +} +export { AssignmentPattern as assignmentPattern }; +export function ArrayPattern(...args: Array): Object { + return builder("ArrayPattern", ...args); +} +export { ArrayPattern as arrayPattern }; +export function ArrowFunctionExpression(...args: Array): Object { + return builder("ArrowFunctionExpression", ...args); +} +export { ArrowFunctionExpression as arrowFunctionExpression }; +export function ClassBody(...args: Array): Object { + return builder("ClassBody", ...args); +} +export { ClassBody as classBody }; +export function ClassDeclaration(...args: Array): Object { + return builder("ClassDeclaration", ...args); +} +export { ClassDeclaration as classDeclaration }; +export function ClassExpression(...args: Array): Object { + return builder("ClassExpression", ...args); +} +export { ClassExpression as classExpression }; +export function ExportAllDeclaration(...args: Array): Object { + return builder("ExportAllDeclaration", ...args); +} +export { ExportAllDeclaration as exportAllDeclaration }; +export function ExportDefaultDeclaration(...args: Array): Object { + return builder("ExportDefaultDeclaration", ...args); +} +export { ExportDefaultDeclaration as exportDefaultDeclaration }; +export function ExportNamedDeclaration(...args: Array): Object { + return builder("ExportNamedDeclaration", ...args); +} +export { ExportNamedDeclaration as exportNamedDeclaration }; +export function ExportSpecifier(...args: Array): Object { + return builder("ExportSpecifier", ...args); +} +export { ExportSpecifier as exportSpecifier }; +export function ForOfStatement(...args: Array): Object { + return builder("ForOfStatement", ...args); +} +export { ForOfStatement as forOfStatement }; +export function ImportDeclaration(...args: Array): Object { + return builder("ImportDeclaration", ...args); +} +export { ImportDeclaration as importDeclaration }; +export function ImportDefaultSpecifier(...args: Array): Object { + return builder("ImportDefaultSpecifier", ...args); +} +export { ImportDefaultSpecifier as importDefaultSpecifier }; +export function ImportNamespaceSpecifier(...args: Array): Object { + return builder("ImportNamespaceSpecifier", ...args); +} +export { ImportNamespaceSpecifier as importNamespaceSpecifier }; +export function ImportSpecifier(...args: Array): Object { + return builder("ImportSpecifier", ...args); +} +export { ImportSpecifier as importSpecifier }; +export function MetaProperty(...args: Array): Object { + return builder("MetaProperty", ...args); +} +export { MetaProperty as metaProperty }; +export function ClassMethod(...args: Array): Object { + return builder("ClassMethod", ...args); +} +export { ClassMethod as classMethod }; +export function ObjectPattern(...args: Array): Object { + return builder("ObjectPattern", ...args); +} +export { ObjectPattern as objectPattern }; +export function SpreadElement(...args: Array): Object { + return builder("SpreadElement", ...args); +} +export { SpreadElement as spreadElement }; +export function Super(...args: Array): Object { + return builder("Super", ...args); +} +export { Super as super }; +export function TaggedTemplateExpression(...args: Array): Object { + return builder("TaggedTemplateExpression", ...args); +} +export { TaggedTemplateExpression as taggedTemplateExpression }; +export function TemplateElement(...args: Array): Object { + return builder("TemplateElement", ...args); +} +export { TemplateElement as templateElement }; +export function TemplateLiteral(...args: Array): Object { + return builder("TemplateLiteral", ...args); +} +export { TemplateLiteral as templateLiteral }; +export function YieldExpression(...args: Array): Object { + return builder("YieldExpression", ...args); +} +export { YieldExpression as yieldExpression }; +export function AnyTypeAnnotation(...args: Array): Object { + return builder("AnyTypeAnnotation", ...args); +} +export { AnyTypeAnnotation as anyTypeAnnotation }; +export function ArrayTypeAnnotation(...args: Array): Object { + return builder("ArrayTypeAnnotation", ...args); +} +export { ArrayTypeAnnotation as arrayTypeAnnotation }; +export function BooleanTypeAnnotation(...args: Array): Object { + return builder("BooleanTypeAnnotation", ...args); +} +export { BooleanTypeAnnotation as booleanTypeAnnotation }; +export function BooleanLiteralTypeAnnotation(...args: Array): Object { + return builder("BooleanLiteralTypeAnnotation", ...args); +} +export { BooleanLiteralTypeAnnotation as booleanLiteralTypeAnnotation }; +export function NullLiteralTypeAnnotation(...args: Array): Object { + return builder("NullLiteralTypeAnnotation", ...args); +} +export { NullLiteralTypeAnnotation as nullLiteralTypeAnnotation }; +export function ClassImplements(...args: Array): Object { + return builder("ClassImplements", ...args); +} +export { ClassImplements as classImplements }; +export function DeclareClass(...args: Array): Object { + return builder("DeclareClass", ...args); +} +export { DeclareClass as declareClass }; +export function DeclareFunction(...args: Array): Object { + return builder("DeclareFunction", ...args); +} +export { DeclareFunction as declareFunction }; +export function DeclareInterface(...args: Array): Object { + return builder("DeclareInterface", ...args); +} +export { DeclareInterface as declareInterface }; +export function DeclareModule(...args: Array): Object { + return builder("DeclareModule", ...args); +} +export { DeclareModule as declareModule }; +export function DeclareModuleExports(...args: Array): Object { + return builder("DeclareModuleExports", ...args); +} +export { DeclareModuleExports as declareModuleExports }; +export function DeclareTypeAlias(...args: Array): Object { + return builder("DeclareTypeAlias", ...args); +} +export { DeclareTypeAlias as declareTypeAlias }; +export function DeclareOpaqueType(...args: Array): Object { + return builder("DeclareOpaqueType", ...args); +} +export { DeclareOpaqueType as declareOpaqueType }; +export function DeclareVariable(...args: Array): Object { + return builder("DeclareVariable", ...args); +} +export { DeclareVariable as declareVariable }; +export function DeclareExportDeclaration(...args: Array): Object { + return builder("DeclareExportDeclaration", ...args); +} +export { DeclareExportDeclaration as declareExportDeclaration }; +export function DeclareExportAllDeclaration(...args: Array): Object { + return builder("DeclareExportAllDeclaration", ...args); +} +export { DeclareExportAllDeclaration as declareExportAllDeclaration }; +export function DeclaredPredicate(...args: Array): Object { + return builder("DeclaredPredicate", ...args); +} +export { DeclaredPredicate as declaredPredicate }; +export function ExistsTypeAnnotation(...args: Array): Object { + return builder("ExistsTypeAnnotation", ...args); +} +export { ExistsTypeAnnotation as existsTypeAnnotation }; +export function FunctionTypeAnnotation(...args: Array): Object { + return builder("FunctionTypeAnnotation", ...args); +} +export { FunctionTypeAnnotation as functionTypeAnnotation }; +export function FunctionTypeParam(...args: Array): Object { + return builder("FunctionTypeParam", ...args); +} +export { FunctionTypeParam as functionTypeParam }; +export function GenericTypeAnnotation(...args: Array): Object { + return builder("GenericTypeAnnotation", ...args); +} +export { GenericTypeAnnotation as genericTypeAnnotation }; +export function InferredPredicate(...args: Array): Object { + return builder("InferredPredicate", ...args); +} +export { InferredPredicate as inferredPredicate }; +export function InterfaceExtends(...args: Array): Object { + return builder("InterfaceExtends", ...args); +} +export { InterfaceExtends as interfaceExtends }; +export function InterfaceDeclaration(...args: Array): Object { + return builder("InterfaceDeclaration", ...args); +} +export { InterfaceDeclaration as interfaceDeclaration }; +export function IntersectionTypeAnnotation(...args: Array): Object { + return builder("IntersectionTypeAnnotation", ...args); +} +export { IntersectionTypeAnnotation as intersectionTypeAnnotation }; +export function MixedTypeAnnotation(...args: Array): Object { + return builder("MixedTypeAnnotation", ...args); +} +export { MixedTypeAnnotation as mixedTypeAnnotation }; +export function EmptyTypeAnnotation(...args: Array): Object { + return builder("EmptyTypeAnnotation", ...args); +} +export { EmptyTypeAnnotation as emptyTypeAnnotation }; +export function NullableTypeAnnotation(...args: Array): Object { + return builder("NullableTypeAnnotation", ...args); +} +export { NullableTypeAnnotation as nullableTypeAnnotation }; +export function NumberLiteralTypeAnnotation(...args: Array): Object { + return builder("NumberLiteralTypeAnnotation", ...args); +} +export { NumberLiteralTypeAnnotation as numberLiteralTypeAnnotation }; +export function NumberTypeAnnotation(...args: Array): Object { + return builder("NumberTypeAnnotation", ...args); +} +export { NumberTypeAnnotation as numberTypeAnnotation }; +export function ObjectTypeAnnotation(...args: Array): Object { + return builder("ObjectTypeAnnotation", ...args); +} +export { ObjectTypeAnnotation as objectTypeAnnotation }; +export function ObjectTypeCallProperty(...args: Array): Object { + return builder("ObjectTypeCallProperty", ...args); +} +export { ObjectTypeCallProperty as objectTypeCallProperty }; +export function ObjectTypeIndexer(...args: Array): Object { + return builder("ObjectTypeIndexer", ...args); +} +export { ObjectTypeIndexer as objectTypeIndexer }; +export function ObjectTypeProperty(...args: Array): Object { + return builder("ObjectTypeProperty", ...args); +} +export { ObjectTypeProperty as objectTypeProperty }; +export function ObjectTypeSpreadProperty(...args: Array): Object { + return builder("ObjectTypeSpreadProperty", ...args); +} +export { ObjectTypeSpreadProperty as objectTypeSpreadProperty }; +export function OpaqueType(...args: Array): Object { + return builder("OpaqueType", ...args); +} +export { OpaqueType as opaqueType }; +export function QualifiedTypeIdentifier(...args: Array): Object { + return builder("QualifiedTypeIdentifier", ...args); +} +export { QualifiedTypeIdentifier as qualifiedTypeIdentifier }; +export function StringLiteralTypeAnnotation(...args: Array): Object { + return builder("StringLiteralTypeAnnotation", ...args); +} +export { StringLiteralTypeAnnotation as stringLiteralTypeAnnotation }; +export function StringTypeAnnotation(...args: Array): Object { + return builder("StringTypeAnnotation", ...args); +} +export { StringTypeAnnotation as stringTypeAnnotation }; +export function ThisTypeAnnotation(...args: Array): Object { + return builder("ThisTypeAnnotation", ...args); +} +export { ThisTypeAnnotation as thisTypeAnnotation }; +export function TupleTypeAnnotation(...args: Array): Object { + return builder("TupleTypeAnnotation", ...args); +} +export { TupleTypeAnnotation as tupleTypeAnnotation }; +export function TypeofTypeAnnotation(...args: Array): Object { + return builder("TypeofTypeAnnotation", ...args); +} +export { TypeofTypeAnnotation as typeofTypeAnnotation }; +export function TypeAlias(...args: Array): Object { + return builder("TypeAlias", ...args); +} +export { TypeAlias as typeAlias }; +export function TypeAnnotation(...args: Array): Object { + return builder("TypeAnnotation", ...args); +} +export { TypeAnnotation as typeAnnotation }; +export function TypeCastExpression(...args: Array): Object { + return builder("TypeCastExpression", ...args); +} +export { TypeCastExpression as typeCastExpression }; +export function TypeParameter(...args: Array): Object { + return builder("TypeParameter", ...args); +} +export { TypeParameter as typeParameter }; +export function TypeParameterDeclaration(...args: Array): Object { + return builder("TypeParameterDeclaration", ...args); +} +export { TypeParameterDeclaration as typeParameterDeclaration }; +export function TypeParameterInstantiation(...args: Array): Object { + return builder("TypeParameterInstantiation", ...args); +} +export { TypeParameterInstantiation as typeParameterInstantiation }; +export function UnionTypeAnnotation(...args: Array): Object { + return builder("UnionTypeAnnotation", ...args); +} +export { UnionTypeAnnotation as unionTypeAnnotation }; +export function VoidTypeAnnotation(...args: Array): Object { + return builder("VoidTypeAnnotation", ...args); +} +export { VoidTypeAnnotation as voidTypeAnnotation }; +export function JSXAttribute(...args: Array): Object { + return builder("JSXAttribute", ...args); +} +export { JSXAttribute as jSXAttribute }; +export function JSXClosingElement(...args: Array): Object { + return builder("JSXClosingElement", ...args); +} +export { JSXClosingElement as jSXClosingElement }; +export function JSXElement(...args: Array): Object { + return builder("JSXElement", ...args); +} +export { JSXElement as jSXElement }; +export function JSXEmptyExpression(...args: Array): Object { + return builder("JSXEmptyExpression", ...args); +} +export { JSXEmptyExpression as jSXEmptyExpression }; +export function JSXExpressionContainer(...args: Array): Object { + return builder("JSXExpressionContainer", ...args); +} +export { JSXExpressionContainer as jSXExpressionContainer }; +export function JSXSpreadChild(...args: Array): Object { + return builder("JSXSpreadChild", ...args); +} +export { JSXSpreadChild as jSXSpreadChild }; +export function JSXIdentifier(...args: Array): Object { + return builder("JSXIdentifier", ...args); +} +export { JSXIdentifier as jSXIdentifier }; +export function JSXMemberExpression(...args: Array): Object { + return builder("JSXMemberExpression", ...args); +} +export { JSXMemberExpression as jSXMemberExpression }; +export function JSXNamespacedName(...args: Array): Object { + return builder("JSXNamespacedName", ...args); +} +export { JSXNamespacedName as jSXNamespacedName }; +export function JSXOpeningElement(...args: Array): Object { + return builder("JSXOpeningElement", ...args); +} +export { JSXOpeningElement as jSXOpeningElement }; +export function JSXSpreadAttribute(...args: Array): Object { + return builder("JSXSpreadAttribute", ...args); +} +export { JSXSpreadAttribute as jSXSpreadAttribute }; +export function JSXText(...args: Array): Object { + return builder("JSXText", ...args); +} +export { JSXText as jSXText }; +export function JSXFragment(...args: Array): Object { + return builder("JSXFragment", ...args); +} +export { JSXFragment as jSXFragment }; +export function JSXOpeningFragment(...args: Array): Object { + return builder("JSXOpeningFragment", ...args); +} +export { JSXOpeningFragment as jSXOpeningFragment }; +export function JSXClosingFragment(...args: Array): Object { + return builder("JSXClosingFragment", ...args); +} +export { JSXClosingFragment as jSXClosingFragment }; +export function Noop(...args: Array): Object { + return builder("Noop", ...args); +} +export { Noop as noop }; +export function ParenthesizedExpression(...args: Array): Object { + return builder("ParenthesizedExpression", ...args); +} +export { ParenthesizedExpression as parenthesizedExpression }; +export function AwaitExpression(...args: Array): Object { + return builder("AwaitExpression", ...args); +} +export { AwaitExpression as awaitExpression }; +export function BindExpression(...args: Array): Object { + return builder("BindExpression", ...args); +} +export { BindExpression as bindExpression }; +export function ClassProperty(...args: Array): Object { + return builder("ClassProperty", ...args); +} +export { ClassProperty as classProperty }; +export function Import(...args: Array): Object { + return builder("Import", ...args); +} +export { Import as import }; +export function Decorator(...args: Array): Object { + return builder("Decorator", ...args); +} +export { Decorator as decorator }; +export function DoExpression(...args: Array): Object { + return builder("DoExpression", ...args); +} +export { DoExpression as doExpression }; +export function ExportDefaultSpecifier(...args: Array): Object { + return builder("ExportDefaultSpecifier", ...args); +} +export { ExportDefaultSpecifier as exportDefaultSpecifier }; +export function ExportNamespaceSpecifier(...args: Array): Object { + return builder("ExportNamespaceSpecifier", ...args); +} +export { ExportNamespaceSpecifier as exportNamespaceSpecifier }; +export function TSParameterProperty(...args: Array): Object { + return builder("TSParameterProperty", ...args); +} +export { TSParameterProperty as tSParameterProperty }; +export function TSDeclareFunction(...args: Array): Object { + return builder("TSDeclareFunction", ...args); +} +export { TSDeclareFunction as tSDeclareFunction }; +export function TSDeclareMethod(...args: Array): Object { + return builder("TSDeclareMethod", ...args); +} +export { TSDeclareMethod as tSDeclareMethod }; +export function TSQualifiedName(...args: Array): Object { + return builder("TSQualifiedName", ...args); +} +export { TSQualifiedName as tSQualifiedName }; +export function TSCallSignatureDeclaration(...args: Array): Object { + return builder("TSCallSignatureDeclaration", ...args); +} +export { TSCallSignatureDeclaration as tSCallSignatureDeclaration }; +export function TSConstructSignatureDeclaration(...args: Array): Object { + return builder("TSConstructSignatureDeclaration", ...args); +} +export { TSConstructSignatureDeclaration as tSConstructSignatureDeclaration }; +export function TSPropertySignature(...args: Array): Object { + return builder("TSPropertySignature", ...args); +} +export { TSPropertySignature as tSPropertySignature }; +export function TSMethodSignature(...args: Array): Object { + return builder("TSMethodSignature", ...args); +} +export { TSMethodSignature as tSMethodSignature }; +export function TSIndexSignature(...args: Array): Object { + return builder("TSIndexSignature", ...args); +} +export { TSIndexSignature as tSIndexSignature }; +export function TSAnyKeyword(...args: Array): Object { + return builder("TSAnyKeyword", ...args); +} +export { TSAnyKeyword as tSAnyKeyword }; +export function TSNumberKeyword(...args: Array): Object { + return builder("TSNumberKeyword", ...args); +} +export { TSNumberKeyword as tSNumberKeyword }; +export function TSObjectKeyword(...args: Array): Object { + return builder("TSObjectKeyword", ...args); +} +export { TSObjectKeyword as tSObjectKeyword }; +export function TSBooleanKeyword(...args: Array): Object { + return builder("TSBooleanKeyword", ...args); +} +export { TSBooleanKeyword as tSBooleanKeyword }; +export function TSStringKeyword(...args: Array): Object { + return builder("TSStringKeyword", ...args); +} +export { TSStringKeyword as tSStringKeyword }; +export function TSSymbolKeyword(...args: Array): Object { + return builder("TSSymbolKeyword", ...args); +} +export { TSSymbolKeyword as tSSymbolKeyword }; +export function TSVoidKeyword(...args: Array): Object { + return builder("TSVoidKeyword", ...args); +} +export { TSVoidKeyword as tSVoidKeyword }; +export function TSUndefinedKeyword(...args: Array): Object { + return builder("TSUndefinedKeyword", ...args); +} +export { TSUndefinedKeyword as tSUndefinedKeyword }; +export function TSNullKeyword(...args: Array): Object { + return builder("TSNullKeyword", ...args); +} +export { TSNullKeyword as tSNullKeyword }; +export function TSNeverKeyword(...args: Array): Object { + return builder("TSNeverKeyword", ...args); +} +export { TSNeverKeyword as tSNeverKeyword }; +export function TSThisType(...args: Array): Object { + return builder("TSThisType", ...args); +} +export { TSThisType as tSThisType }; +export function TSFunctionType(...args: Array): Object { + return builder("TSFunctionType", ...args); +} +export { TSFunctionType as tSFunctionType }; +export function TSConstructorType(...args: Array): Object { + return builder("TSConstructorType", ...args); +} +export { TSConstructorType as tSConstructorType }; +export function TSTypeReference(...args: Array): Object { + return builder("TSTypeReference", ...args); +} +export { TSTypeReference as tSTypeReference }; +export function TSTypePredicate(...args: Array): Object { + return builder("TSTypePredicate", ...args); +} +export { TSTypePredicate as tSTypePredicate }; +export function TSTypeQuery(...args: Array): Object { + return builder("TSTypeQuery", ...args); +} +export { TSTypeQuery as tSTypeQuery }; +export function TSTypeLiteral(...args: Array): Object { + return builder("TSTypeLiteral", ...args); +} +export { TSTypeLiteral as tSTypeLiteral }; +export function TSArrayType(...args: Array): Object { + return builder("TSArrayType", ...args); +} +export { TSArrayType as tSArrayType }; +export function TSTupleType(...args: Array): Object { + return builder("TSTupleType", ...args); +} +export { TSTupleType as tSTupleType }; +export function TSUnionType(...args: Array): Object { + return builder("TSUnionType", ...args); +} +export { TSUnionType as tSUnionType }; +export function TSIntersectionType(...args: Array): Object { + return builder("TSIntersectionType", ...args); +} +export { TSIntersectionType as tSIntersectionType }; +export function TSParenthesizedType(...args: Array): Object { + return builder("TSParenthesizedType", ...args); +} +export { TSParenthesizedType as tSParenthesizedType }; +export function TSTypeOperator(...args: Array): Object { + return builder("TSTypeOperator", ...args); +} +export { TSTypeOperator as tSTypeOperator }; +export function TSIndexedAccessType(...args: Array): Object { + return builder("TSIndexedAccessType", ...args); +} +export { TSIndexedAccessType as tSIndexedAccessType }; +export function TSMappedType(...args: Array): Object { + return builder("TSMappedType", ...args); +} +export { TSMappedType as tSMappedType }; +export function TSLiteralType(...args: Array): Object { + return builder("TSLiteralType", ...args); +} +export { TSLiteralType as tSLiteralType }; +export function TSExpressionWithTypeArguments(...args: Array): Object { + return builder("TSExpressionWithTypeArguments", ...args); +} +export { TSExpressionWithTypeArguments as tSExpressionWithTypeArguments }; +export function TSInterfaceDeclaration(...args: Array): Object { + return builder("TSInterfaceDeclaration", ...args); +} +export { TSInterfaceDeclaration as tSInterfaceDeclaration }; +export function TSInterfaceBody(...args: Array): Object { + return builder("TSInterfaceBody", ...args); +} +export { TSInterfaceBody as tSInterfaceBody }; +export function TSTypeAliasDeclaration(...args: Array): Object { + return builder("TSTypeAliasDeclaration", ...args); +} +export { TSTypeAliasDeclaration as tSTypeAliasDeclaration }; +export function TSAsExpression(...args: Array): Object { + return builder("TSAsExpression", ...args); +} +export { TSAsExpression as tSAsExpression }; +export function TSTypeAssertion(...args: Array): Object { + return builder("TSTypeAssertion", ...args); +} +export { TSTypeAssertion as tSTypeAssertion }; +export function TSEnumDeclaration(...args: Array): Object { + return builder("TSEnumDeclaration", ...args); +} +export { TSEnumDeclaration as tSEnumDeclaration }; +export function TSEnumMember(...args: Array): Object { + return builder("TSEnumMember", ...args); +} +export { TSEnumMember as tSEnumMember }; +export function TSModuleDeclaration(...args: Array): Object { + return builder("TSModuleDeclaration", ...args); +} +export { TSModuleDeclaration as tSModuleDeclaration }; +export function TSModuleBlock(...args: Array): Object { + return builder("TSModuleBlock", ...args); +} +export { TSModuleBlock as tSModuleBlock }; +export function TSImportEqualsDeclaration(...args: Array): Object { + return builder("TSImportEqualsDeclaration", ...args); +} +export { TSImportEqualsDeclaration as tSImportEqualsDeclaration }; +export function TSExternalModuleReference(...args: Array): Object { + return builder("TSExternalModuleReference", ...args); +} +export { TSExternalModuleReference as tSExternalModuleReference }; +export function TSNonNullExpression(...args: Array): Object { + return builder("TSNonNullExpression", ...args); +} +export { TSNonNullExpression as tSNonNullExpression }; +export function TSExportAssignment(...args: Array): Object { + return builder("TSExportAssignment", ...args); +} +export { TSExportAssignment as tSExportAssignment }; +export function TSNamespaceExportDeclaration(...args: Array): Object { + return builder("TSNamespaceExportDeclaration", ...args); +} +export { TSNamespaceExportDeclaration as tSNamespaceExportDeclaration }; +export function TSTypeAnnotation(...args: Array): Object { + return builder("TSTypeAnnotation", ...args); +} +export { TSTypeAnnotation as tSTypeAnnotation }; +export function TSTypeParameterInstantiation(...args: Array): Object { + return builder("TSTypeParameterInstantiation", ...args); +} +export { TSTypeParameterInstantiation as tSTypeParameterInstantiation }; +export function TSTypeParameterDeclaration(...args: Array): Object { + return builder("TSTypeParameterDeclaration", ...args); +} +export { TSTypeParameterDeclaration as tSTypeParameterDeclaration }; +export function TSTypeParameter(...args: Array): Object { + return builder("TSTypeParameter", ...args); +} +export { TSTypeParameter as tSTypeParameter }; +export function NumberLiteral(...args: Array): Object { + console.trace( + "The node type NumberLiteral has been renamed to NumericLiteral", + ); + return NumberLiteral("NumberLiteral", ...args); +} +export { NumberLiteral as numberLiteral }; +export function RegexLiteral(...args: Array): Object { + console.trace("The node type RegexLiteral has been renamed to RegExpLiteral"); + return RegexLiteral("RegexLiteral", ...args); +} +export { RegexLiteral as regexLiteral }; +export function RestProperty(...args: Array): Object { + console.trace("The node type RestProperty has been renamed to RestElement"); + return RestProperty("RestProperty", ...args); +} +export { RestProperty as restProperty }; +export function SpreadProperty(...args: Array): Object { + console.trace( + "The node type SpreadProperty has been renamed to SpreadElement", + ); + return SpreadProperty("SpreadProperty", ...args); +} +export { SpreadProperty as spreadProperty }; diff --git a/packages/babel-types/src/builders/react/buildChildren.js b/packages/babel-types/src/builders/react/buildChildren.js new file mode 100644 index 0000000000..dc2c470caa --- /dev/null +++ b/packages/babel-types/src/builders/react/buildChildren.js @@ -0,0 +1,27 @@ +// @flow +import { + isJSXText, + isJSXExpressionContainer, + isJSXEmptyExpression, +} from "../../validators/generated"; +import cleanJSXElementLiteralChild from "../../utils/react/cleanJSXElementLiteralChild"; + +export default function buildChildren(node: Object): Array { + const elements = []; + + for (let i = 0; i < node.children.length; i++) { + let child = node.children[i]; + + if (isJSXText(child)) { + cleanJSXElementLiteralChild(child, elements); + continue; + } + + if (isJSXExpressionContainer(child)) child = child.expression; + if (isJSXEmptyExpression(child)) continue; + + elements.push(child); + } + + return elements; +} diff --git a/packages/babel-types/src/clone/clone.js b/packages/babel-types/src/clone/clone.js new file mode 100644 index 0000000000..c3b1537890 --- /dev/null +++ b/packages/babel-types/src/clone/clone.js @@ -0,0 +1,16 @@ +// @flow + +/** + * Create a shallow clone of a `node` excluding `_private` properties. + */ +export default function clone(node: T): T { + if (!node) return node; + const newNode = (({}: any): T); + + Object.keys(node).forEach(key => { + if (key[0] === "_") return; + newNode[key] = node[key]; + }); + + return newNode; +} diff --git a/packages/babel-types/src/clone/cloneDeep.js b/packages/babel-types/src/clone/cloneDeep.js new file mode 100644 index 0000000000..25a5252dc5 --- /dev/null +++ b/packages/babel-types/src/clone/cloneDeep.js @@ -0,0 +1,28 @@ +// @flow + +/** + * Create a deep clone of a `node` and all of it's child nodes + * excluding `_private` properties. + */ +export default function cloneDeep(node: T): T { + if (!node) return node; + const newNode = (({}: any): T); + + Object.keys(node).forEach(key => { + if (key[0] === "_") return; + + let val = node[key]; + + if (val) { + if (val.type) { + val = cloneDeep(val); + } else if (Array.isArray(val)) { + val = val.map(cloneDeep); + } + } + + newNode[key] = val; + }); + + return newNode; +} diff --git a/packages/babel-types/src/clone/cloneWithoutLoc.js b/packages/babel-types/src/clone/cloneWithoutLoc.js new file mode 100644 index 0000000000..f495f94b8f --- /dev/null +++ b/packages/babel-types/src/clone/cloneWithoutLoc.js @@ -0,0 +1,12 @@ +// @flow +import clone from "./clone"; + +/** + * Create a shallow clone of a `node` excluding `_private` and location properties. + */ +export default function cloneWithoutLoc(node: T): T { + const newNode = clone(node); + newNode.loc = null; + + return newNode; +} diff --git a/packages/babel-types/src/comments/addComment.js b/packages/babel-types/src/comments/addComment.js new file mode 100644 index 0000000000..1a7482fb18 --- /dev/null +++ b/packages/babel-types/src/comments/addComment.js @@ -0,0 +1,19 @@ +// @flow +import addComments from "./addComments"; + +/** + * Add comment of certain type to a node. + */ +export default function addComment( + node: T, + type: string, + content: string, + line?: boolean, +): T { + return addComments(node, type, [ + { + type: line ? "CommentLine" : "CommentBlock", + value: content, + }, + ]); +} diff --git a/packages/babel-types/src/comments/addComments.js b/packages/babel-types/src/comments/addComments.js new file mode 100644 index 0000000000..7652ae37f9 --- /dev/null +++ b/packages/babel-types/src/comments/addComments.js @@ -0,0 +1,26 @@ +// @flow + +/** + * Add comments of certain type to a node. + */ +export default function addComments( + node: T, + type: string, + comments: Array, +): T { + if (!comments || !node) return node; + + const key = `${type}Comments`; + + if (node[key]) { + if (type === "leading") { + node[key] = comments.concat(node[key]); + } else { + node[key] = node[key].concat(comments); + } + } else { + node[key] = comments; + } + + return node; +} diff --git a/packages/babel-types/src/comments/inheritInnerComments.js b/packages/babel-types/src/comments/inheritInnerComments.js new file mode 100644 index 0000000000..04153c0a25 --- /dev/null +++ b/packages/babel-types/src/comments/inheritInnerComments.js @@ -0,0 +1,9 @@ +// @flow +import inherit from "../utils/inherit"; + +export default function inheritInnerComments( + child: Object, + parent: Object, +): void { + inherit("innerComments", child, parent); +} diff --git a/packages/babel-types/src/comments/inheritLeadingComments.js b/packages/babel-types/src/comments/inheritLeadingComments.js new file mode 100644 index 0000000000..fadcb9a0eb --- /dev/null +++ b/packages/babel-types/src/comments/inheritLeadingComments.js @@ -0,0 +1,9 @@ +// @flow +import inherit from "../utils/inherit"; + +export default function inheritLeadingComments( + child: Object, + parent: Object, +): void { + inherit("leadingComments", child, parent); +} diff --git a/packages/babel-types/src/comments/inheritTrailingComments.js b/packages/babel-types/src/comments/inheritTrailingComments.js new file mode 100644 index 0000000000..502f71f5c3 --- /dev/null +++ b/packages/babel-types/src/comments/inheritTrailingComments.js @@ -0,0 +1,9 @@ +// @flow +import inherit from "../utils/inherit"; + +export default function inheritTrailingComments( + child: Object, + parent: Object, +): void { + inherit("trailingComments", child, parent); +} diff --git a/packages/babel-types/src/comments/inheritsComments.js b/packages/babel-types/src/comments/inheritsComments.js new file mode 100644 index 0000000000..5135c963b2 --- /dev/null +++ b/packages/babel-types/src/comments/inheritsComments.js @@ -0,0 +1,18 @@ +// @flow +import inheritTrailingComments from "./inheritTrailingComments"; +import inheritLeadingComments from "./inheritLeadingComments"; +import inheritInnerComments from "./inheritInnerComments"; + +/** + * Inherit all unique comments from `parent` node to `child` node. + */ +export default function inheritsComments( + child: T, + parent: Object, +): T { + inheritTrailingComments(child, parent); + inheritLeadingComments(child, parent); + inheritInnerComments(child, parent); + + return child; +} diff --git a/packages/babel-types/src/comments/removeComments.js b/packages/babel-types/src/comments/removeComments.js new file mode 100644 index 0000000000..317ab07094 --- /dev/null +++ b/packages/babel-types/src/comments/removeComments.js @@ -0,0 +1,13 @@ +// @flow +import { COMMENT_KEYS } from "../constants"; + +/** + * Remove comment properties from a node. + */ +export default function removeComments(node: T): T { + COMMENT_KEYS.forEach(key => { + node[key] = null; + }); + + return node; +} diff --git a/packages/babel-types/src/constants/generated/index.js b/packages/babel-types/src/constants/generated/index.js new file mode 100644 index 0000000000..793d436c99 --- /dev/null +++ b/packages/babel-types/src/constants/generated/index.js @@ -0,0 +1,49 @@ +// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import { FLIPPED_ALIAS_KEYS } from "../../definitions"; + +export const EXPRESSION_TYPES = FLIPPED_ALIAS_KEYS["Expression"]; +export const BINARY_TYPES = FLIPPED_ALIAS_KEYS["Binary"]; +export const SCOPABLE_TYPES = FLIPPED_ALIAS_KEYS["Scopable"]; +export const BLOCKPARENT_TYPES = FLIPPED_ALIAS_KEYS["BlockParent"]; +export const BLOCK_TYPES = FLIPPED_ALIAS_KEYS["Block"]; +export const STATEMENT_TYPES = FLIPPED_ALIAS_KEYS["Statement"]; +export const TERMINATORLESS_TYPES = FLIPPED_ALIAS_KEYS["Terminatorless"]; +export const COMPLETIONSTATEMENT_TYPES = + FLIPPED_ALIAS_KEYS["CompletionStatement"]; +export const CONDITIONAL_TYPES = FLIPPED_ALIAS_KEYS["Conditional"]; +export const LOOP_TYPES = FLIPPED_ALIAS_KEYS["Loop"]; +export const WHILE_TYPES = FLIPPED_ALIAS_KEYS["While"]; +export const EXPRESSIONWRAPPER_TYPES = FLIPPED_ALIAS_KEYS["ExpressionWrapper"]; +export const FOR_TYPES = FLIPPED_ALIAS_KEYS["For"]; +export const FORXSTATEMENT_TYPES = FLIPPED_ALIAS_KEYS["ForXStatement"]; +export const FUNCTION_TYPES = FLIPPED_ALIAS_KEYS["Function"]; +export const FUNCTIONPARENT_TYPES = FLIPPED_ALIAS_KEYS["FunctionParent"]; +export const PUREISH_TYPES = FLIPPED_ALIAS_KEYS["Pureish"]; +export const DECLARATION_TYPES = FLIPPED_ALIAS_KEYS["Declaration"]; +export const PATTERNLIKE_TYPES = FLIPPED_ALIAS_KEYS["PatternLike"]; +export const LVAL_TYPES = FLIPPED_ALIAS_KEYS["LVal"]; +export const TSENTITYNAME_TYPES = FLIPPED_ALIAS_KEYS["TSEntityName"]; +export const LITERAL_TYPES = FLIPPED_ALIAS_KEYS["Literal"]; +export const IMMUTABLE_TYPES = FLIPPED_ALIAS_KEYS["Immutable"]; +export const USERWHITESPACABLE_TYPES = FLIPPED_ALIAS_KEYS["UserWhitespacable"]; +export const METHOD_TYPES = FLIPPED_ALIAS_KEYS["Method"]; +export const OBJECTMEMBER_TYPES = FLIPPED_ALIAS_KEYS["ObjectMember"]; +export const PROPERTY_TYPES = FLIPPED_ALIAS_KEYS["Property"]; +export const UNARYLIKE_TYPES = FLIPPED_ALIAS_KEYS["UnaryLike"]; +export const PATTERN_TYPES = FLIPPED_ALIAS_KEYS["Pattern"]; +export const CLASS_TYPES = FLIPPED_ALIAS_KEYS["Class"]; +export const MODULEDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ModuleDeclaration"]; +export const EXPORTDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["ExportDeclaration"]; +export const MODULESPECIFIER_TYPES = FLIPPED_ALIAS_KEYS["ModuleSpecifier"]; +export const FLOW_TYPES = FLIPPED_ALIAS_KEYS["Flow"]; +export const FLOWBASEANNOTATION_TYPES = + FLIPPED_ALIAS_KEYS["FlowBaseAnnotation"]; +export const FLOWDECLARATION_TYPES = FLIPPED_ALIAS_KEYS["FlowDeclaration"]; +export const FLOWPREDICATE_TYPES = FLIPPED_ALIAS_KEYS["FlowPredicate"]; +export const JSX_TYPES = FLIPPED_ALIAS_KEYS["JSX"]; +export const TSTYPEELEMENT_TYPES = FLIPPED_ALIAS_KEYS["TSTypeElement"]; +export const TSTYPE_TYPES = FLIPPED_ALIAS_KEYS["TSType"]; diff --git a/packages/babel-types/src/constants.js b/packages/babel-types/src/constants/index.js similarity index 80% rename from packages/babel-types/src/constants.js rename to packages/babel-types/src/constants/index.js index ec46a48253..b777caa0f1 100644 --- a/packages/babel-types/src/constants.js +++ b/packages/babel-types/src/constants/index.js @@ -1,5 +1,4 @@ -/* eslint max-len: "off" */ - +// @flow export const STATEMENT_OR_BLOCK_KEYS = ["consequent", "body", "alternate"]; export const FLATTENABLE_KEYS = ["body", "expressions"]; export const FOR_INIT_KEYS = ["left", "init"]; @@ -62,30 +61,3 @@ export const BLOCK_SCOPED_SYMBOL = Symbol.for("var used to be block scoped"); export const NOT_LOCAL_BINDING = Symbol.for( "should not be considered a local binding", ); - -export const RESERVED_WORDS_ES3_ONLY = new Set([ - "abstract", - "boolean", - "byte", - "char", - "double", - "enum", - "final", - "float", - "goto", - "implements", - "int", - "interface", - "long", - "native", - "package", - "private", - "protected", - "public", - "short", - "static", - "synchronized", - "throws", - "transient", - "volatile", -]); diff --git a/packages/babel-types/src/converters.js b/packages/babel-types/src/converters.js deleted file mode 100644 index b895a748d2..0000000000 --- a/packages/babel-types/src/converters.js +++ /dev/null @@ -1,321 +0,0 @@ -import isPlainObject from "lodash/isPlainObject"; -import isRegExp from "lodash/isRegExp"; -import type { Scope } from "@babel/traverse"; -import * as t from "./index"; - -export function toComputedKey( - node: Object, - key: Object = node.key || node.property, -): Object { - if (!node.computed) { - if (t.isIdentifier(key)) key = t.stringLiteral(key.name); - } - return key; -} - -function gatherSequenceExpressions( - nodes: Array, - scope: Scope, - declars: Array, -): ?Object { - const exprs = []; - let ensureLastUndefined = true; - - for (const node of nodes) { - ensureLastUndefined = false; - - if (t.isExpression(node)) { - exprs.push(node); - } else if (t.isExpressionStatement(node)) { - exprs.push(node.expression); - } else if (t.isVariableDeclaration(node)) { - if (node.kind !== "var") return; // bailed - - for (const declar of (node.declarations: Array)) { - const bindings = t.getBindingIdentifiers(declar); - for (const key in bindings) { - declars.push({ - kind: node.kind, - id: bindings[key], - }); - } - - if (declar.init) { - exprs.push(t.assignmentExpression("=", declar.id, declar.init)); - } - } - - ensureLastUndefined = true; - } else if (t.isIfStatement(node)) { - const consequent = node.consequent - ? gatherSequenceExpressions([node.consequent], scope, declars) - : scope.buildUndefinedNode(); - const alternate = node.alternate - ? gatherSequenceExpressions([node.alternate], scope, declars) - : scope.buildUndefinedNode(); - if (!consequent || !alternate) return; // bailed - - exprs.push(t.conditionalExpression(node.test, consequent, alternate)); - } else if (t.isBlockStatement(node)) { - const body = gatherSequenceExpressions(node.body, scope, declars); - if (!body) return; // bailed - - exprs.push(body); - } else if (t.isEmptyStatement(node)) { - // empty statement so ensure the last item is undefined if we're last - ensureLastUndefined = true; - } else { - // bailed, we can't turn this statement into an expression - return; - } - } - - if (ensureLastUndefined) { - exprs.push(scope.buildUndefinedNode()); - } - - if (exprs.length === 1) { - return exprs[0]; - } else { - return t.sequenceExpression(exprs); - } -} - -/** - * Turn an array of statement `nodes` into a `SequenceExpression`. - * - * Variable declarations are turned into simple assignments and their - * declarations hoisted to the top of the current scope. - * - * Expression statements are just resolved to their expression. - */ - -export function toSequenceExpression( - nodes: Array, - scope: Scope, -): ?Object { - if (!nodes || !nodes.length) return; - - const declars = []; - const result = gatherSequenceExpressions(nodes, scope, declars); - if (!result) return; - - for (const declar of declars) { - scope.push(declar); - } - - return result; -} - -export function toKeyAlias(node: Object, key: Object = node.key): string { - let alias; - - if (node.kind === "method") { - return toKeyAlias.increment() + ""; - } else if (t.isIdentifier(key)) { - alias = key.name; - } else if (t.isStringLiteral(key)) { - alias = JSON.stringify(key.value); - } else { - alias = JSON.stringify(t.removePropertiesDeep(t.cloneDeep(key))); - } - - if (node.computed) { - alias = `[${alias}]`; - } - - if (node.static) { - alias = `static:${alias}`; - } - - return alias; -} - -toKeyAlias.uid = 0; - -toKeyAlias.increment = function() { - if (toKeyAlias.uid >= Number.MAX_SAFE_INTEGER) { - return (toKeyAlias.uid = 0); - } else { - return toKeyAlias.uid++; - } -}; - -export function toIdentifier(name: string): string { - name = name + ""; - - // replace all non-valid identifiers with dashes - name = name.replace(/[^a-zA-Z0-9$_]/g, "-"); - - // remove all dashes and numbers from start of name - name = name.replace(/^[-0-9]+/, ""); - - // camel case - name = name.replace(/[-\s]+(.)?/g, function(match, c) { - return c ? c.toUpperCase() : ""; - }); - - if (!t.isValidIdentifier(name)) { - name = `_${name}`; - } - - return name || "_"; -} - -export function toBindingIdentifierName(name: string): string { - name = toIdentifier(name); - if (name === "eval" || name === "arguments") name = "_" + name; - return name; -} - -/** - * [Please add a description.] - * @returns {Object|Boolean} - */ - -export function toStatement(node: Object, ignore?: boolean) { - if (t.isStatement(node)) { - return node; - } - - let mustHaveId = false; - let newType; - - if (t.isClass(node)) { - mustHaveId = true; - newType = "ClassDeclaration"; - } else if (t.isFunction(node)) { - mustHaveId = true; - newType = "FunctionDeclaration"; - } else if (t.isAssignmentExpression(node)) { - return t.expressionStatement(node); - } - - if (mustHaveId && !node.id) { - newType = false; - } - - if (!newType) { - if (ignore) { - return false; - } else { - throw new Error(`cannot turn ${node.type} to a statement`); - } - } - - node.type = newType; - - return node; -} - -export function toExpression(node: Object): Object { - if (t.isExpressionStatement(node)) { - node = node.expression; - } - - // return unmodified node - // important for things like ArrowFunctions where - // type change from ArrowFunction to FunctionExpression - // produces bugs like -> `()=>a` to `function () a` - // without generating a BlockStatement for it - // ref: https://github.com/babel/babili/issues/130 - if (t.isExpression(node)) { - return node; - } - - // convert all classes and functions - // ClassDeclaration -> ClassExpression - // FunctionDeclaration, ObjectMethod, ClassMethod -> FunctionExpression - if (t.isClass(node)) { - node.type = "ClassExpression"; - } else if (t.isFunction(node)) { - node.type = "FunctionExpression"; - } - - // if it's still not an expression - if (!t.isExpression(node)) { - throw new Error(`cannot turn ${node.type} to an expression`); - } - - return node; -} - -export function toBlock(node: Object, parent: Object): Object { - if (t.isBlockStatement(node)) { - return node; - } - - if (t.isEmptyStatement(node)) { - node = []; - } - - if (!Array.isArray(node)) { - if (!t.isStatement(node)) { - if (t.isFunction(parent)) { - node = t.returnStatement(node); - } else { - node = t.expressionStatement(node); - } - } - - node = [node]; - } - - return t.blockStatement(node); -} - -export function valueToNode(value: any): Object { - // undefined - if (value === undefined) { - return t.identifier("undefined"); - } - - // boolean - if (value === true || value === false) { - return t.booleanLiteral(value); - } - - // null - if (value === null) { - return t.nullLiteral(); - } - - // strings - if (typeof value === "string") { - return t.stringLiteral(value); - } - - // numbers - if (typeof value === "number") { - return t.numericLiteral(value); - } - - // regexes - if (isRegExp(value)) { - const pattern = value.source; - const flags = value.toString().match(/\/([a-z]+|)$/)[1]; - return t.regExpLiteral(pattern, flags); - } - - // array - if (Array.isArray(value)) { - return t.arrayExpression(value.map(t.valueToNode)); - } - - // object - if (isPlainObject(value)) { - const props = []; - for (const key in value) { - let nodeKey; - if (t.isValidIdentifier(key)) { - nodeKey = t.identifier(key); - } else { - nodeKey = t.stringLiteral(key); - } - props.push(t.objectProperty(nodeKey, t.valueToNode(value[key]))); - } - return t.objectExpression(props); - } - - throw new Error("don't know how to turn this value into a node"); -} diff --git a/packages/babel-types/src/converters/ensureBlock.js b/packages/babel-types/src/converters/ensureBlock.js new file mode 100644 index 0000000000..ee02d46eea --- /dev/null +++ b/packages/babel-types/src/converters/ensureBlock.js @@ -0,0 +1,15 @@ +// @flow +import toBlock from "./toBlock"; + +/** + * Ensure the `key` (defaults to "body") of a `node` is a block. + * Casting it to a block if it is not. + * + * Returns the BlockStatement + */ +export default function ensureBlock( + node: Object, + key: string = "body", +): Object { + return (node[key] = toBlock(node[key], node)); +} diff --git a/packages/babel-types/src/converters/gatherSequenceExpressions.js b/packages/babel-types/src/converters/gatherSequenceExpressions.js new file mode 100644 index 0000000000..779f362114 --- /dev/null +++ b/packages/babel-types/src/converters/gatherSequenceExpressions.js @@ -0,0 +1,84 @@ +// @flow +import type { Scope } from "@babel/traverse"; +import getBindingIdentifiers from "../retrievers/getBindingIdentifiers"; +import { + isExpression, + isExpressionStatement, + isVariableDeclaration, + isIfStatement, + isBlockStatement, + isEmptyStatement, +} from "../validators/generated"; +import { + sequenceExpression, + assignmentExpression, + conditionalExpression, +} from "../builders/generated"; + +export default function gatherSequenceExpressions( + nodes: Array, + scope: Scope, + declars: Array, +): ?Object { + const exprs = []; + let ensureLastUndefined = true; + + for (const node of nodes) { + ensureLastUndefined = false; + + if (isExpression(node)) { + exprs.push(node); + } else if (isExpressionStatement(node)) { + exprs.push(node.expression); + } else if (isVariableDeclaration(node)) { + if (node.kind !== "var") return; // bailed + + for (const declar of (node.declarations: Array)) { + const bindings = getBindingIdentifiers(declar); + for (const key in bindings) { + declars.push({ + kind: node.kind, + id: bindings[key], + }); + } + + if (declar.init) { + exprs.push(assignmentExpression("=", declar.id, declar.init)); + } + } + + ensureLastUndefined = true; + } else if (isIfStatement(node)) { + const consequent = node.consequent + ? gatherSequenceExpressions([node.consequent], scope, declars) + : scope.buildUndefinedNode(); + const alternate = node.alternate + ? gatherSequenceExpressions([node.alternate], scope, declars) + : scope.buildUndefinedNode(); + if (!consequent || !alternate) return; // bailed + + exprs.push(conditionalExpression(node.test, consequent, alternate)); + } else if (isBlockStatement(node)) { + const body = gatherSequenceExpressions(node.body, scope, declars); + if (!body) return; // bailed + + exprs.push(body); + } else if (isEmptyStatement(node)) { + // empty statement so ensure the last item is undefined if we're last + ensureLastUndefined = true; + } else { + // bailed, we can't turn this statement into an expression + return; + } + } + + if (ensureLastUndefined) { + exprs.push(scope.buildUndefinedNode()); + } + + if (exprs.length === 1) { + return exprs[0]; + } else { + return sequenceExpression(exprs); + } +} diff --git a/packages/babel-types/src/converters/toBindingIdentifierName.js b/packages/babel-types/src/converters/toBindingIdentifierName.js new file mode 100644 index 0000000000..a7cac3a8e9 --- /dev/null +++ b/packages/babel-types/src/converters/toBindingIdentifierName.js @@ -0,0 +1,9 @@ +// @flow +import toIdentifier from "./toIdentifier"; + +export default function toBindingIdentifierName(name: string): string { + name = toIdentifier(name); + if (name === "eval" || name === "arguments") name = "_" + name; + + return name; +} diff --git a/packages/babel-types/src/converters/toBlock.js b/packages/babel-types/src/converters/toBlock.js new file mode 100644 index 0000000000..1086b792e5 --- /dev/null +++ b/packages/babel-types/src/converters/toBlock.js @@ -0,0 +1,36 @@ +// @flow +import { + isBlockStatement, + isFunction, + isEmptyStatement, + isStatement, +} from "../validators/generated"; +import { + returnStatement, + expressionStatement, + blockStatement, +} from "../builders/generated"; + +export default function toBlock(node: Object, parent: Object): Object { + if (isBlockStatement(node)) { + return node; + } + + let blockNodes = []; + + if (isEmptyStatement(node)) { + blockNodes = []; + } else { + if (!isStatement(node)) { + if (isFunction(parent)) { + node = returnStatement(node); + } else { + node = expressionStatement(node); + } + } + + blockNodes = [node]; + } + + return blockStatement(blockNodes); +} diff --git a/packages/babel-types/src/converters/toComputedKey.js b/packages/babel-types/src/converters/toComputedKey.js new file mode 100644 index 0000000000..a09ced3a41 --- /dev/null +++ b/packages/babel-types/src/converters/toComputedKey.js @@ -0,0 +1,12 @@ +// @flow +import { isIdentifier } from "../validators/generated"; +import { stringLiteral } from "../builders/generated"; + +export default function toComputedKey( + node: Object, + key: Object = node.key || node.property, +): Object { + if (!node.computed && isIdentifier(key)) key = stringLiteral(key.name); + + return key; +} diff --git a/packages/babel-types/src/converters/toExpression.js b/packages/babel-types/src/converters/toExpression.js new file mode 100644 index 0000000000..15c98b7f7d --- /dev/null +++ b/packages/babel-types/src/converters/toExpression.js @@ -0,0 +1,39 @@ +// @flow +import { + isExpression, + isFunction, + isClass, + isExpressionStatement, +} from "../validators/generated"; + +export default function toExpression(node: Object): Object { + if (isExpressionStatement(node)) { + node = node.expression; + } + + // return unmodified node + // important for things like ArrowFunctions where + // type change from ArrowFunction to FunctionExpression + // produces bugs like -> `()=>a` to `function () a` + // without generating a BlockStatement for it + // ref: https://github.com/babel/babili/issues/130 + if (isExpression(node)) { + return node; + } + + // convert all classes and functions + // ClassDeclaration -> ClassExpression + // FunctionDeclaration, ObjectMethod, ClassMethod -> FunctionExpression + if (isClass(node)) { + node.type = "ClassExpression"; + } else if (isFunction(node)) { + node.type = "FunctionExpression"; + } + + // if it's still not an expression + if (!isExpression(node)) { + throw new Error(`cannot turn ${node.type} to an expression`); + } + + return node; +} diff --git a/packages/babel-types/src/converters/toIdentifier.js b/packages/babel-types/src/converters/toIdentifier.js new file mode 100644 index 0000000000..21ed978484 --- /dev/null +++ b/packages/babel-types/src/converters/toIdentifier.js @@ -0,0 +1,23 @@ +// @flow +import isValidIdentifier from "../validators/isValidIdentifier"; + +export default function toIdentifier(name: string): string { + name = name + ""; + + // replace all non-valid identifiers with dashes + name = name.replace(/[^a-zA-Z0-9$_]/g, "-"); + + // remove all dashes and numbers from start of name + name = name.replace(/^[-0-9]+/, ""); + + // camel case + name = name.replace(/[-\s]+(.)?/g, function(match, c) { + return c ? c.toUpperCase() : ""; + }); + + if (!isValidIdentifier(name)) { + name = `_${name}`; + } + + return name || "_"; +} diff --git a/packages/babel-types/src/converters/toKeyAlias.js b/packages/babel-types/src/converters/toKeyAlias.js new file mode 100644 index 0000000000..29d781f1c8 --- /dev/null +++ b/packages/babel-types/src/converters/toKeyAlias.js @@ -0,0 +1,41 @@ +// @flow +import { isIdentifier, isStringLiteral } from "../validators/generated"; +import cloneDeep from "../clone/cloneDeep"; +import removePropertiesDeep from "../modifications/removePropertiesDeep"; + +export default function toKeyAlias( + node: Object, + key: Object = node.key, +): string { + let alias; + + if (node.kind === "method") { + return toKeyAlias.increment() + ""; + } else if (isIdentifier(key)) { + alias = key.name; + } else if (isStringLiteral(key)) { + alias = JSON.stringify(key.value); + } else { + alias = JSON.stringify(removePropertiesDeep(cloneDeep(key))); + } + + if (node.computed) { + alias = `[${alias}]`; + } + + if (node.static) { + alias = `static:${alias}`; + } + + return alias; +} + +toKeyAlias.uid = 0; + +toKeyAlias.increment = function() { + if (toKeyAlias.uid >= Number.MAX_SAFE_INTEGER) { + return (toKeyAlias.uid = 0); + } else { + return toKeyAlias.uid++; + } +}; diff --git a/packages/babel-types/src/converters/toSequenceExpression.js b/packages/babel-types/src/converters/toSequenceExpression.js new file mode 100644 index 0000000000..4ea5d1ca8c --- /dev/null +++ b/packages/babel-types/src/converters/toSequenceExpression.js @@ -0,0 +1,28 @@ +// @flow +import type { Scope } from "@babel/traverse"; +import gatherSequenceExpressions from "./gatherSequenceExpressions"; + +/** + * Turn an array of statement `nodes` into a `SequenceExpression`. + * + * Variable declarations are turned into simple assignments and their + * declarations hoisted to the top of the current scope. + * + * Expression statements are just resolved to their expression. + */ +export default function toSequenceExpression( + nodes: Array, + scope: Scope, +): ?Object { + if (!nodes || !nodes.length) return; + + const declars = []; + const result = gatherSequenceExpressions(nodes, scope, declars); + if (!result) return; + + for (const declar of declars) { + scope.push(declar); + } + + return result; +} diff --git a/packages/babel-types/src/converters/toStatement.js b/packages/babel-types/src/converters/toStatement.js new file mode 100644 index 0000000000..8f9ce505a3 --- /dev/null +++ b/packages/babel-types/src/converters/toStatement.js @@ -0,0 +1,43 @@ +// @flow +import { + isStatement, + isFunction, + isClass, + isAssignmentExpression, +} from "../validators/generated"; +import { expressionStatement } from "../builders/generated"; + +export default function toStatement(node: Object, ignore?: boolean) { + if (isStatement(node)) { + return node; + } + + let mustHaveId = false; + let newType; + + if (isClass(node)) { + mustHaveId = true; + newType = "ClassDeclaration"; + } else if (isFunction(node)) { + mustHaveId = true; + newType = "FunctionDeclaration"; + } else if (isAssignmentExpression(node)) { + return expressionStatement(node); + } + + if (mustHaveId && !node.id) { + newType = false; + } + + if (!newType) { + if (ignore) { + return false; + } else { + throw new Error(`cannot turn ${node.type} to a statement`); + } + } + + node.type = newType; + + return node; +} diff --git a/packages/babel-types/src/converters/valueToNode.js b/packages/babel-types/src/converters/valueToNode.js new file mode 100644 index 0000000000..85aca82e0a --- /dev/null +++ b/packages/babel-types/src/converters/valueToNode.js @@ -0,0 +1,71 @@ +// @flow +import isPlainObject from "lodash/isPlainObject"; +import isRegExp from "lodash/isRegExp"; +import isValidIdentifier from "../validators/isValidIdentifier"; +import { + identifier, + booleanLiteral, + nullLiteral, + stringLiteral, + numericLiteral, + regExpLiteral, + arrayExpression, + objectProperty, + objectExpression, +} from "../builders/generated"; + +export default function valueToNode(value: any): Object { + // undefined + if (value === undefined) { + return identifier("undefined"); + } + + // boolean + if (value === true || value === false) { + return booleanLiteral(value); + } + + // null + if (value === null) { + return nullLiteral(); + } + + // strings + if (typeof value === "string") { + return stringLiteral(value); + } + + // numbers + if (typeof value === "number") { + return numericLiteral(value); + } + + // regexes + if (isRegExp(value)) { + const pattern = value.source; + const flags = value.toString().match(/\/([a-z]+|)$/)[1]; + return regExpLiteral(pattern, flags); + } + + // array + if (Array.isArray(value)) { + return arrayExpression(value.map(valueToNode)); + } + + // object + if (isPlainObject(value)) { + const props = []; + for (const key in value) { + let nodeKey; + if (isValidIdentifier(key)) { + nodeKey = identifier(key); + } else { + nodeKey = stringLiteral(key); + } + props.push(objectProperty(nodeKey, valueToNode(value[key]))); + } + return objectExpression(props); + } + + throw new Error("don't know how to turn this value into a node"); +} diff --git a/packages/babel-types/src/definitions/core.js b/packages/babel-types/src/definitions/core.js index 597aad960b..b811c7b994 100644 --- a/packages/babel-types/src/definitions/core.js +++ b/packages/babel-types/src/definitions/core.js @@ -1,5 +1,5 @@ // @flow -import * as t from "../index"; +import isValidIdentifier from "../validators/isValidIdentifier"; import { BINARY_OPERATORS, @@ -15,7 +15,7 @@ import defineType, { assertEach, chain, assertOneOf, -} from "./index"; +} from "./utils"; defineType("ArrayExpression", { fields: { @@ -372,7 +372,7 @@ defineType("Identifier", { ...patternLikeCommon, name: { validate(node, key, val) { - if (!t.isValidIdentifier(val)) { + if (!isValidIdentifier(val)) { // throw new TypeError(`"${val}" is not a valid identifer name`); } }, diff --git a/packages/babel-types/src/definitions/es2015.js b/packages/babel-types/src/definitions/es2015.js index f45f09db4d..a508ee00ca 100644 --- a/packages/babel-types/src/definitions/es2015.js +++ b/packages/babel-types/src/definitions/es2015.js @@ -5,7 +5,7 @@ import defineType, { chain, assertEach, assertOneOf, -} from "./index"; +} from "./utils"; import { functionCommon, patternLikeCommon } from "./core"; defineType("AssignmentPattern", { diff --git a/packages/babel-types/src/definitions/experimental.js b/packages/babel-types/src/definitions/experimental.js index 69925f54af..2859f099c2 100644 --- a/packages/babel-types/src/definitions/experimental.js +++ b/packages/babel-types/src/definitions/experimental.js @@ -4,7 +4,7 @@ import defineType, { assertNodeType, assertValueType, chain, -} from "./index"; +} from "./utils"; import { classMethodOrPropertyCommon } from "./es2015"; defineType("AwaitExpression", { diff --git a/packages/babel-types/src/definitions/flow.js b/packages/babel-types/src/definitions/flow.js index 3e722abc5e..f165ec346e 100644 --- a/packages/babel-types/src/definitions/flow.js +++ b/packages/babel-types/src/definitions/flow.js @@ -4,7 +4,7 @@ import defineType, { assertNodeType, assertValueType, chain, -} from "./index"; +} from "./utils"; defineType("AnyTypeAnnotation", { aliases: ["Flow", "FlowBaseAnnotation"], diff --git a/packages/babel-types/src/definitions/index.js b/packages/babel-types/src/definitions/index.js index eec228e457..6ffd136e23 100644 --- a/packages/babel-types/src/definitions/index.js +++ b/packages/babel-types/src/definitions/index.js @@ -1,177 +1,39 @@ // @flow -import * as t from "../index"; +import toFastProperties from "to-fast-properties"; +import "./core"; +import "./es2015"; +import "./flow"; +import "./jsx"; +import "./misc"; +import "./experimental"; +import "./typescript"; +import { + VISITOR_KEYS, + ALIAS_KEYS, + FLIPPED_ALIAS_KEYS, + NODE_FIELDS, + BUILDER_KEYS, + DEPRECATED_KEYS, +} from "./utils"; -export const VISITOR_KEYS = {}; -export const ALIAS_KEYS = {}; -export const NODE_FIELDS = {}; -export const BUILDER_KEYS = {}; -export const DEPRECATED_KEYS = {}; +// We do this here, because at this point the visitor keys should be ready and setup +toFastProperties(VISITOR_KEYS); +toFastProperties(ALIAS_KEYS); +toFastProperties(FLIPPED_ALIAS_KEYS); +toFastProperties(NODE_FIELDS); +toFastProperties(BUILDER_KEYS); +toFastProperties(DEPRECATED_KEYS); -function getType(val) { - if (Array.isArray(val)) { - return "array"; - } else if (val === null) { - return "null"; - } else if (val === undefined) { - return "undefined"; - } else { - return typeof val; - } -} +const TYPES = Object.keys(VISITOR_KEYS) + .concat(Object.keys(FLIPPED_ALIAS_KEYS)) + .concat(Object.keys(DEPRECATED_KEYS)); -export function assertEach(callback: Function): Function { - function validator(node, key, val) { - if (!Array.isArray(val)) return; - - for (let i = 0; i < val.length; i++) { - callback(node, `${key}[${i}]`, val[i]); - } - } - validator.each = callback; - return validator; -} - -export function assertOneOf(...vals: Array): Function { - function validate(node: Object, key: string, val: any): void { - if (vals.indexOf(val) < 0) { - throw new TypeError( - `Property ${key} expected value to be one of ${JSON.stringify( - vals, - )} but got ${JSON.stringify(val)}`, - ); - } - } - - validate.oneOf = vals; - - return validate; -} - -export function assertNodeType(...types: Array): Function { - function validate(node, key, val) { - let valid = false; - - for (const type of types) { - if (t.is(type, val)) { - valid = true; - break; - } - } - - if (!valid) { - throw new TypeError( - `Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify( - types, - )} ` + `but instead got ${JSON.stringify(val && val.type)}`, - ); - } - } - - validate.oneOfNodeTypes = types; - - return validate; -} - -export function assertNodeOrValueType(...types: Array): Function { - function validate(node, key, val) { - let valid = false; - - for (const type of types) { - if (getType(val) === type || t.is(type, val)) { - valid = true; - break; - } - } - - if (!valid) { - throw new TypeError( - `Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify( - types, - )} ` + `but instead got ${JSON.stringify(val && val.type)}`, - ); - } - } - - validate.oneOfNodeOrValueTypes = types; - - return validate; -} - -export function assertValueType(type: string): Function { - function validate(node, key, val) { - const valid = getType(val) === type; - - if (!valid) { - throw new TypeError( - `Property ${key} expected type of ${type} but got ${getType(val)}`, - ); - } - } - - validate.type = type; - - return validate; -} - -export function chain(...fns: Array): Function { - function validate(...args) { - for (const fn of fns) { - fn(...args); - } - } - validate.chainOf = fns; - return validate; -} - -export default function defineType( - type: string, - opts: { - fields?: { - [string]: {| validate?: Function, default?: any, optional?: boolean |}, - }, - visitor?: Array, - aliases?: Array, - builder?: Array, - inherits?: string, - deprecatedAlias?: string, - } = {}, -) { - const inherits = (opts.inherits && store[opts.inherits]) || {}; - - const fields = opts.fields || inherits.fields || {}; - const visitor = opts.visitor || inherits.visitor || []; - const aliases = opts.aliases || inherits.aliases || []; - const builder = opts.builder || inherits.builder || opts.visitor || []; - - if (opts.deprecatedAlias) { - DEPRECATED_KEYS[opts.deprecatedAlias] = type; - } - - // ensure all field keys are represented in `fields` - for (const key of (visitor.concat(builder): Array)) { - // $FlowIssue - fields[key] = fields[key] || {}; - } - - for (const key in fields) { - const field = fields[key]; - - if (builder.indexOf(key) === -1) { - field.optional = true; - } - if (field.default === undefined) { - field.default = null; - } else if (!field.validate) { - field.validate = assertValueType(getType(field.default)); - } - } - - VISITOR_KEYS[type] = opts.visitor = visitor; - BUILDER_KEYS[type] = opts.builder = builder; - NODE_FIELDS[type] = opts.fields = fields; - ALIAS_KEYS[type] = opts.aliases = aliases; - - store[type] = opts; -} - -const store = {}; +export { + VISITOR_KEYS, + ALIAS_KEYS, + FLIPPED_ALIAS_KEYS, + NODE_FIELDS, + BUILDER_KEYS, + DEPRECATED_KEYS, + TYPES, +}; diff --git a/packages/babel-types/src/definitions/init.js b/packages/babel-types/src/definitions/init.js deleted file mode 100644 index b367ebfa21..0000000000 --- a/packages/babel-types/src/definitions/init.js +++ /dev/null @@ -1,8 +0,0 @@ -import "./index"; -import "./core"; -import "./es2015"; -import "./flow"; -import "./jsx"; -import "./misc"; -import "./experimental"; -import "./typescript"; diff --git a/packages/babel-types/src/definitions/jsx.js b/packages/babel-types/src/definitions/jsx.js index 90c759350d..ecac6a49ed 100644 --- a/packages/babel-types/src/definitions/jsx.js +++ b/packages/babel-types/src/definitions/jsx.js @@ -4,7 +4,7 @@ import defineType, { assertValueType, chain, assertEach, -} from "./index"; +} from "./utils"; defineType("JSXAttribute", { visitor: ["name", "value"], diff --git a/packages/babel-types/src/definitions/misc.js b/packages/babel-types/src/definitions/misc.js index 0c2c5e68a4..2fc1334aac 100644 --- a/packages/babel-types/src/definitions/misc.js +++ b/packages/babel-types/src/definitions/misc.js @@ -1,5 +1,5 @@ // @flow -import defineType, { assertNodeType } from "./index"; +import defineType, { assertNodeType } from "./utils"; defineType("Noop", { visitor: [], diff --git a/packages/babel-types/src/definitions/typescript.js b/packages/babel-types/src/definitions/typescript.js index 5fcaba0df6..83b9d0acb5 100644 --- a/packages/babel-types/src/definitions/typescript.js +++ b/packages/babel-types/src/definitions/typescript.js @@ -1,12 +1,11 @@ // @flow - import defineType, { assertEach, assertNodeType, assertOneOf, assertValueType, chain, -} from "./index"; +} from "./utils"; import { functionDeclarationCommon } from "./core"; import { classMethodOrDeclareMethodCommon } from "./es2015"; diff --git a/packages/babel-types/src/definitions/utils.js b/packages/babel-types/src/definitions/utils.js new file mode 100644 index 0000000000..d87826a30a --- /dev/null +++ b/packages/babel-types/src/definitions/utils.js @@ -0,0 +1,182 @@ +// @flow +import is from "../validators/is"; + +export const VISITOR_KEYS: { [string]: Array } = {}; +export const ALIAS_KEYS: { [string]: Array } = {}; +export const FLIPPED_ALIAS_KEYS: { [string]: Array } = {}; +export const NODE_FIELDS: { [string]: {} } = {}; +export const BUILDER_KEYS: { [string]: Array } = {}; +export const DEPRECATED_KEYS: { [string]: string } = {}; + +function getType(val) { + if (Array.isArray(val)) { + return "array"; + } else if (val === null) { + return "null"; + } else if (val === undefined) { + return "undefined"; + } else { + return typeof val; + } +} + +export function assertEach(callback: Function): Function { + function validator(node, key, val) { + if (!Array.isArray(val)) return; + + for (let i = 0; i < val.length; i++) { + callback(node, `${key}[${i}]`, val[i]); + } + } + validator.each = callback; + return validator; +} + +export function assertOneOf(...values: Array): Function { + function validate(node: Object, key: string, val: any) { + if (values.indexOf(val) < 0) { + throw new TypeError( + `Property ${key} expected value to be one of ${JSON.stringify( + values, + )} but got ${JSON.stringify(val)}`, + ); + } + } + + validate.oneOf = values; + + return validate; +} + +export function assertNodeType(...types: Array): Function { + function validate(node, key, val) { + let valid = false; + + for (const type of types) { + if (is(type, val)) { + valid = true; + break; + } + } + + if (!valid) { + throw new TypeError( + `Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify( + types, + )} ` + `but instead got ${JSON.stringify(val && val.type)}`, + ); + } + } + + validate.oneOfNodeTypes = types; + + return validate; +} + +export function assertNodeOrValueType(...types: Array): Function { + function validate(node, key, val) { + let valid = false; + + for (const type of types) { + if (getType(val) === type || is(type, val)) { + valid = true; + break; + } + } + + if (!valid) { + throw new TypeError( + `Property ${key} of ${node.type} expected node to be of a type ${JSON.stringify( + types, + )} ` + `but instead got ${JSON.stringify(val && val.type)}`, + ); + } + } + + validate.oneOfNodeOrValueTypes = types; + + return validate; +} + +export function assertValueType(type: string): Function { + function validate(node, key, val) { + const valid = getType(val) === type; + + if (!valid) { + throw new TypeError( + `Property ${key} expected type of ${type} but got ${getType(val)}`, + ); + } + } + + validate.type = type; + + return validate; +} + +export function chain(...fns: Array): Function { + function validate(...args) { + for (const fn of fns) { + fn(...args); + } + } + validate.chainOf = fns; + return validate; +} + +export default function defineType( + type: string, + opts: { + fields?: { + [string]: {| validate?: Function, default?: any, optional?: boolean |}, + }, + visitor?: Array, + aliases?: Array, + builder?: Array, + inherits?: string, + deprecatedAlias?: string, + } = {}, +) { + const inherits = (opts.inherits && store[opts.inherits]) || {}; + + const fields: Object = opts.fields || inherits.fields || {}; + const visitor: Array = opts.visitor || inherits.visitor || []; + const aliases: Array = opts.aliases || inherits.aliases || []; + const builder: Array = + opts.builder || inherits.builder || opts.visitor || []; + + if (opts.deprecatedAlias) { + DEPRECATED_KEYS[opts.deprecatedAlias] = type; + } + + // ensure all field keys are represented in `fields` + for (const key of (visitor.concat(builder): Array)) { + fields[key] = fields[key] || {}; + } + + for (const key in fields) { + const field = fields[key]; + + if (builder.indexOf(key) === -1) { + field.optional = true; + } + if (field.default === undefined) { + field.default = null; + } else if (!field.validate) { + field.validate = assertValueType(getType(field.default)); + } + } + + VISITOR_KEYS[type] = opts.visitor = visitor; + BUILDER_KEYS[type] = opts.builder = builder; + NODE_FIELDS[type] = opts.fields = fields; + ALIAS_KEYS[type] = opts.aliases = aliases; + aliases.forEach(alias => { + FLIPPED_ALIAS_KEYS[alias] = FLIPPED_ALIAS_KEYS[alias] || []; + FLIPPED_ALIAS_KEYS[alias].push(type); + }); + + store[type] = opts; +} + +const store = {}; diff --git a/packages/babel-types/src/index.js b/packages/babel-types/src/index.js index 9288ea4515..f4c280b9fa 100644 --- a/packages/babel-types/src/index.js +++ b/packages/babel-types/src/index.js @@ -1,601 +1,123 @@ -import toFastProperties from "to-fast-properties"; -import loClone from "lodash/clone"; -import uniq from "lodash/uniq"; +// @flow +import isReactComponent from "./validators/react/isReactComponent"; +import isCompatTag from "./validators/react/isCompatTag"; +import buildChildren from "./builders/react/buildChildren"; -const t = exports; - -/** - * Registers `is[Type]` and `assert[Type]` generated functions for a given `type`. - * Pass `skipAliasCheck` to force it to directly compare `node.type` with `type`. - */ - -function registerType(type: string) { - let is = t[`is${type}`]; - if (!is) { - is = t[`is${type}`] = function(node, opts) { - return t.is(type, node, opts); - }; - } - - t[`assert${type}`] = function(node, opts) { - opts = opts || {}; - if (!is(node, opts)) { - throw new Error( - `Expected type ${JSON.stringify(type)} with option ${JSON.stringify( - opts, - )}`, - ); - } - }; -} - -// +// asserts +export { default as assertNode } from "./asserts/assertNode"; +export * from "./asserts/generated"; +//builders export { - STATEMENT_OR_BLOCK_KEYS, - FLATTENABLE_KEYS, - FOR_INIT_KEYS, - COMMENT_KEYS, - LOGICAL_OPERATORS, - UPDATE_OPERATORS, - BOOLEAN_NUMBER_BINARY_OPERATORS, - EQUALITY_BINARY_OPERATORS, - COMPARISON_BINARY_OPERATORS, - BOOLEAN_BINARY_OPERATORS, - NUMBER_BINARY_OPERATORS, - BINARY_OPERATORS, - BOOLEAN_UNARY_OPERATORS, - NUMBER_UNARY_OPERATORS, - STRING_UNARY_OPERATORS, - UNARY_OPERATORS, - INHERIT_KEYS, - BLOCK_SCOPED_SYMBOL, - NOT_LOCAL_BINDING, -} from "./constants"; - -import "./definitions/init"; -import { - VISITOR_KEYS, - ALIAS_KEYS, - NODE_FIELDS, - BUILDER_KEYS, - DEPRECATED_KEYS, -} from "./definitions"; -export { VISITOR_KEYS, ALIAS_KEYS, NODE_FIELDS, BUILDER_KEYS, DEPRECATED_KEYS }; - -import * as _react from "./react"; -export { _react as react }; - -import { traverse, traverseFast } from "./traverse"; -export { traverse, traverseFast }; - -/** - * Registers `is[Type]` and `assert[Type]` for all types. - */ - -for (const type in t.VISITOR_KEYS) { - registerType(type); -} - -/** - * Flip `ALIAS_KEYS` for faster access in the reverse direction. - */ - -t.FLIPPED_ALIAS_KEYS = {}; - -Object.keys(t.ALIAS_KEYS).forEach(function(type) { - t.ALIAS_KEYS[type].forEach(function(alias) { - const types = (t.FLIPPED_ALIAS_KEYS[alias] = - t.FLIPPED_ALIAS_KEYS[alias] || []); - types.push(type); - }); -}); - -/** - * Registers `is[Alias]` and `assert[Alias]` functions for all aliases. - */ - -Object.keys(t.FLIPPED_ALIAS_KEYS).forEach(function(type) { - t[type.toUpperCase() + "_TYPES"] = t.FLIPPED_ALIAS_KEYS[type]; - registerType(type); -}); - -export const TYPES = Object.keys(t.VISITOR_KEYS) - .concat(Object.keys(t.FLIPPED_ALIAS_KEYS)) - .concat(Object.keys(t.DEPRECATED_KEYS)); - -/** - * Returns whether `node` is of given `type`. - * - * For better performance, use this instead of `is[Type]` when `type` is unknown. - * Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`. - */ - -export function is(type: string, node: Object, opts?: Object): boolean { - if (!node) return false; - - const matches = isType(node.type, type); - if (!matches) return false; - - if (typeof opts === "undefined") { - return true; - } else { - return t.shallowEqual(node, opts); - } -} - -/** - * Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`. - */ - -export function isType(nodeType: string, targetType: string): boolean { - if (nodeType === targetType) return true; - - // This is a fast-path. If the test above failed, but an alias key is found, then the - // targetType was a primary node type, so there's no need to check the aliases. - if (t.ALIAS_KEYS[targetType]) return false; - - const aliases: ?Array = t.FLIPPED_ALIAS_KEYS[targetType]; - if (aliases) { - if (aliases[0] === nodeType) return true; - - for (const alias of aliases) { - if (nodeType === alias) return true; - } - } - - return false; -} - -/** - * Description - */ - -Object.keys(t.BUILDER_KEYS).forEach(function(type) { - const keys = t.BUILDER_KEYS[type]; - - function builder() { - if (arguments.length > keys.length) { - throw new Error( - `t.${type}: Too many arguments passed. Received ${arguments.length} but can receive ` + - `no more than ${keys.length}`, - ); - } - - const node = {}; - node.type = type; - - let i = 0; - - for (const key of (keys: Array)) { - const field = t.NODE_FIELDS[type][key]; - - let arg = arguments[i++]; - if (arg === undefined) arg = loClone(field.default); - - node[key] = arg; - } - - for (const key in node) { - validate(node, key, node[key]); - } - - return node; - } - - t[type] = builder; - t[type[0].toLowerCase() + type.slice(1)] = builder; -}); - -/** - * Description - */ - -for (const type in t.DEPRECATED_KEYS) { - const newType = t.DEPRECATED_KEYS[type]; - - function proxy(fn) { - return function() { - console.trace(`The node type ${type} has been renamed to ${newType}`); - return fn.apply(this, arguments); - }; - } - - t[type] = t[type[0].toLowerCase() + type.slice(1)] = proxy(t[newType]); - t[`is${type}`] = proxy(t[`is${newType}`]); - t[`assert${type}`] = proxy(t[`assert${newType}`]); -} - -/** - * Description - */ - -export function validate(node?: Object, key: string, val: any) { - if (!node) return; - - const fields = t.NODE_FIELDS[node.type]; - if (!fields) return; - - const field = fields[key]; - if (!field || !field.validate) return; - if (field.optional && val == null) return; - - field.validate(node, key, val); -} - -/** - * Test if an object is shallowly equal. - */ - -export function shallowEqual(actual: Object, expected: Object): boolean { - const keys = Object.keys(expected); - - for (const key of (keys: Array)) { - if (actual[key] !== expected[key]) { - return false; - } - } - - return true; -} - -/** - * Append a node to a member expression. - */ - -export function appendToMemberExpression( - member: Object, - append: Object, - computed?: boolean, -): Object { - member.object = t.memberExpression( - member.object, - member.property, - member.computed, - ); - member.property = append; - member.computed = !!computed; - return member; -} - -/** - * Prepend a node to a member expression. - */ - -export function prependToMemberExpression( - member: Object, - prepend: Object, -): Object { - member.object = t.memberExpression(prepend, member.object); - return member; -} - -/** - * Ensure the `key` (defaults to "body") of a `node` is a block. - * Casting it to a block if it is not. - */ - -export function ensureBlock(node: Object, key: string = "body"): Object { - return (node[key] = t.toBlock(node[key], node)); -} - -/** - * Create a shallow clone of a `node` excluding `_private` properties. - */ - -export function clone(node: Object): Object { - if (!node) return node; - const newNode = {}; - for (const key in node) { - if (key[0] === "_") continue; - newNode[key] = node[key]; - } - return newNode; -} - -/** - * Create a shallow clone of a `node` excluding `_private` and location properties. - */ - -export function cloneWithoutLoc(node: Object): Object { - const newNode = clone(node); - newNode.loc = null; - return newNode; -} - -/** - * Create a deep clone of a `node` and all of it's child nodes - * exluding `_private` properties. - */ - -export function cloneDeep(node: Object): Object { - if (!node) return node; - const newNode = {}; - - for (const key in node) { - if (key[0] === "_") continue; - - let val = node[key]; - - if (val) { - if (val.type) { - val = t.cloneDeep(val); - } else if (Array.isArray(val)) { - val = val.map(t.cloneDeep); - } - } - - newNode[key] = val; - } - - return newNode; -} - -/** - * Determines whether or not the input node `member` matches the - * input `match`. - * - * For example, given the match `React.createClass` it would match the - * parsed nodes of `React.createClass` and `React["createClass"]`. - */ - -export function matchesPattern( - member: Object, - match: string | Array, - allowPartial?: boolean, -): boolean { - // not a member expression - if (!t.isMemberExpression(member)) return false; - - const parts = Array.isArray(match) ? match : match.split("."); - const nodes = []; - - let node; - for (node = member; t.isMemberExpression(node); node = node.object) { - nodes.push(node.property); - } - nodes.push(node); - - if (nodes.length < parts.length) return false; - if (!allowPartial && nodes.length > parts.length) return false; - - for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) { - const node = nodes[j]; - let value; - if (t.isIdentifier(node)) { - value = node.name; - } else if (t.isStringLiteral(node)) { - value = node.value; - } else { - return false; - } - - if (parts[i] !== value) return false; - } - - return true; -} - -/** - * Build a function that when called will return whether or not the - * input `node` `MemberExpression` matches the input `match`. - * - * For example, given the match `React.createClass` it would match the - * parsed nodes of `React.createClass` and `React["createClass"]`. - */ - -export function buildMatchMemberExpression( - match: string, - allowPartial?: boolean, -): Object => boolean { - const parts = match.split("."); - return function(member) { - return matchesPattern(member, parts, allowPartial); - }; -} - -/** - * Add comment of certain type to a node. - */ - -export function addComment( - node: Object, - type: string, - content: string, - line?: boolean, -): Object { - addComments(node, type, [ - { - type: line ? "CommentLine" : "CommentBlock", - value: content, - }, - ]); -} - -/** - * Add comments of certain type to a node. - */ - -export function addComments( - node: Object, - type: string, - comments: Array, -): Object { - if (!comments || !node) return; - - const key = `${type}Comments`; - - if (node[key]) { - if (type === "leading") { - node[key] = comments.concat(node[key]); - } else { - node[key] = node[key].concat(comments); - } - } else { - node[key] = comments; - } - return node; -} - -/** - * Remove comment properties from a node. - */ - -export function removeComments(node: Object): Object { - for (const key of t.COMMENT_KEYS) { - node[key] = null; - } - return node; -} - -/** - * Inherit all unique comments from `parent` node to `child` node. - */ - -export function inheritsComments(child: Object, parent: Object): Object { - inheritTrailingComments(child, parent); - inheritLeadingComments(child, parent); - inheritInnerComments(child, parent); - return child; -} - -export function inheritTrailingComments(child: Object, parent: Object) { - _inheritComments("trailingComments", child, parent); -} - -export function inheritLeadingComments(child: Object, parent: Object) { - _inheritComments("leadingComments", child, parent); -} - -export function inheritInnerComments(child: Object, parent: Object) { - _inheritComments("innerComments", child, parent); -} - -function _inheritComments(key, child, parent) { - if (child && parent) { - child[key] = uniq([].concat(child[key], parent[key]).filter(Boolean)); - } -} - -/** - * Inherit all contextual properties from `parent` node to `child` node. - */ - -export function inherits(child: Object, parent: Object): Object { - if (!child || !parent) return child; - - // optionally inherit specific properties if not null - for (const key of (t.INHERIT_KEYS.optional: Array)) { - if (child[key] == null) { - child[key] = parent[key]; - } - } - - // force inherit "private" properties - for (const key in parent) { - if (key[0] === "_" && key !== "__clone") child[key] = parent[key]; - } - - // force inherit select properties - for (const key of (t.INHERIT_KEYS.force: Array)) { - child[key] = parent[key]; - } - - t.inheritsComments(child, parent); - - return child; -} - -/** - * TODO - */ - -export function assertNode(node?) { - if (!isNode(node)) { - // $FlowFixMe - throw new TypeError("Not a valid node " + (node && node.type)); - } -} - -/** - * TODO - */ - -export function isNode(node?): boolean { - return !!(node && VISITOR_KEYS[node.type]); -} - -// Optimize property access. -toFastProperties(t); -toFastProperties(t.VISITOR_KEYS); - -const CLEAR_KEYS: Array = ["tokens", "start", "end", "loc", "raw", "rawValue"]; - -const CLEAR_KEYS_PLUS_COMMENTS: Array = t.COMMENT_KEYS - .concat(["comments"]) - .concat(CLEAR_KEYS); - -/** - * Remove all of the _* properties from a node along with the additional metadata - * properties like location data and raw token data. - */ - -export function removeProperties(node: Node, opts?: Object): void { - opts = opts || {}; - const map = opts.preserveComments ? CLEAR_KEYS : CLEAR_KEYS_PLUS_COMMENTS; - for (const key of map) { - if (node[key] != null) node[key] = undefined; - } - - for (const key in node) { - if (key[0] === "_" && node[key] != null) node[key] = undefined; - } - - const syms: Array = Object.getOwnPropertySymbols(node); - for (const sym of syms) { - node[sym] = null; - } -} - -export function removePropertiesDeep(tree: Node, opts?: Object): Node { - traverseFast(tree, removeProperties, opts); - return tree; -} - -// + default as createTypeAnnotationBasedOnTypeof, +} from "./builders/flow/createTypeAnnotationBasedOnTypeof"; export { - getBindingIdentifiers, - getOuterBindingIdentifiers, -} from "./retrievers"; + default as createUnionTypeAnnotation, +} from "./builders/flow/createUnionTypeAnnotation"; +export * from "./builders/generated"; -export { - isBinding, - isReferenced, - isValidIdentifier, - isValidES3Identifier, - isLet, - isBlockScoped, - isVar, - isSpecifierDefault, - isScope, - isImmutable, - isNodesEquivalent, -} from "./validators"; +// clone +export { default as clone } from "./clone/clone"; +export { default as cloneDeep } from "./clone/cloneDeep"; +export { default as cloneWithoutLoc } from "./clone/cloneWithoutLoc"; +// comments +export { default as addComment } from "./comments/addComment"; +export { default as addComments } from "./comments/addComments"; export { - toComputedKey, - toSequenceExpression, - toKeyAlias, - toIdentifier, - toBindingIdentifierName, - toStatement, - toExpression, - toBlock, - valueToNode, -} from "./converters"; + default as inheritInnerComments, +} from "./comments/inheritInnerComments"; +export { + default as inheritLeadingComments, +} from "./comments/inheritLeadingComments"; +export { default as inheritsComments } from "./comments/inheritsComments"; +export { + default as inheritTrailingComments, +} from "./comments/inheritTrailingComments"; +export { default as removeComments } from "./comments/removeComments"; +// constants +export * from "./constants/generated"; +export * from "./constants"; + +// converters +export { default as ensureBlock } from "./converters/ensureBlock"; export { - createUnionTypeAnnotation, - removeTypeDuplicates, - createTypeAnnotationBasedOnTypeof, -} from "./flow"; + default as toBindingIdentifierName, +} from "./converters/toBindingIdentifierName"; +export { default as toBlock } from "./converters/toBlock"; +export { default as toComputedKey } from "./converters/toComputedKey"; +export { default as toExpression } from "./converters/toExpression"; +export { default as toIdentifier } from "./converters/toIdentifier"; +export { default as toKeyAlias } from "./converters/toKeyAlias"; +export { + default as toSequenceExpression, +} from "./converters/toSequenceExpression"; +export { default as toStatement } from "./converters/toStatement"; +export { default as valueToNode } from "./converters/valueToNode"; + +// definitions +export * from "./definitions"; + +// modifications +export { + default as appendToMemberExpression, +} from "./modifications/appendToMemberExpression"; +export { default as inherits } from "./modifications/inherits"; +export { + default as prependToMemberExpression, +} from "./modifications/prependToMemberExpression"; +export { default as removeProperties } from "./modifications/removeProperties"; +export { + default as removePropertiesDeep, +} from "./modifications/removePropertiesDeep"; +export { + default as removeTypeDuplicates, +} from "./modifications/flow/removeTypeDuplicates"; + +// retrievers +export { + default as getBindingIdentifiers, +} from "./retrievers/getBindingIdentifiers"; +export { + default as getOuterBindingIdentifiers, +} from "./retrievers/getOuterBindingIdentifiers"; + +// traverse +export { default as traverse } from "./traverse/traverse"; +export type * from "./traverse/traverse"; +export { default as traverseFast } from "./traverse/traverseFast"; + +// utils +export { default as shallowEqual } from "./utils/shallowEqual"; + +// validators +export { default as is } from "./validators/is"; +export { default as isBinding } from "./validators/isBinding"; +export { default as isBlockScoped } from "./validators/isBlockScoped"; +export { default as isImmutable } from "./validators/isImmutable"; +export { default as isLet } from "./validators/isLet"; +export { default as isNode } from "./validators/isNode"; +export { default as isNodesEquivalent } from "./validators/isNodesEquivalent"; +export { default as isReferenced } from "./validators/isReferenced"; +export { default as isScope } from "./validators/isScope"; +export { default as isSpecifierDefault } from "./validators/isSpecifierDefault"; +export { default as isType } from "./validators/isType"; +export { + default as isValidES3Identifier, +} from "./validators/isValidES3Identifier"; +export { default as isValidIdentifier } from "./validators/isValidIdentifier"; +export { default as isVar } from "./validators/isVar"; +export { default as matchesPattern } from "./validators/matchesPattern"; +export { default as validate } from "./validators/validate"; +export { + default as buildMatchMemberExpression, +} from "./validators/buildMatchMemberExpression"; +export * from "./validators/generated"; + +// react +export const react = { + isReactComponent, + isCompatTag, + buildChildren, +}; diff --git a/packages/babel-types/src/modifications/appendToMemberExpression.js b/packages/babel-types/src/modifications/appendToMemberExpression.js new file mode 100644 index 0000000000..1232ce6af3 --- /dev/null +++ b/packages/babel-types/src/modifications/appendToMemberExpression.js @@ -0,0 +1,21 @@ +// @flow +import { memberExpression } from "../builders/generated"; + +/** + * Append a node to a member expression. + */ +export default function appendToMemberExpression( + member: T, + append: Object, + computed?: boolean = false, +): T { + member.object = memberExpression( + member.object, + member.property, + member.computed, + ); + member.property = append; + member.computed = !!computed; + + return member; +} diff --git a/packages/babel-types/src/flow.js b/packages/babel-types/src/modifications/flow/removeTypeDuplicates.js similarity index 50% rename from packages/babel-types/src/flow.js rename to packages/babel-types/src/modifications/flow/removeTypeDuplicates.js index a1d0063e70..d27a8d2571 100644 --- a/packages/babel-types/src/flow.js +++ b/packages/babel-types/src/modifications/flow/removeTypeDuplicates.js @@ -1,25 +1,17 @@ -import * as t from "./index"; - -/** - * Takes an array of `types` and flattens them, removing duplicates and - * returns a `UnionTypeAnnotation` node containg them. - */ - -export function createUnionTypeAnnotation(types: Array) { - const flattened = removeTypeDuplicates(types); - - if (flattened.length === 1) { - return flattened[0]; - } else { - return t.unionTypeAnnotation(flattened); - } -} +// @flow +import { + isAnyTypeAnnotation, + isGenericTypeAnnotation, + isUnionTypeAnnotation, + isFlowBaseAnnotation, +} from "../../validators/generated"; /** * Dedupe type annotations. */ - -export function removeTypeDuplicates(nodes: Array): Array { +export default function removeTypeDuplicates( + nodes: Array, +): Array { const generics = {}; const bases = {}; @@ -38,18 +30,16 @@ export function removeTypeDuplicates(nodes: Array): Array { } // this type matches anything - if (t.isAnyTypeAnnotation(node)) { + if (isAnyTypeAnnotation(node)) { return [node]; } - // - if (t.isFlowBaseAnnotation(node)) { + if (isFlowBaseAnnotation(node)) { bases[node.type] = node; continue; } - // - if (t.isUnionTypeAnnotation(node)) { + if (isUnionTypeAnnotation(node)) { if (typeGroups.indexOf(node.types) < 0) { nodes = nodes.concat(node.types); typeGroups.push(node.types); @@ -58,7 +48,7 @@ export function removeTypeDuplicates(nodes: Array): Array { } // find a matching generic type and merge and deduplicate the type parameters - if (t.isGenericTypeAnnotation(node)) { + if (isGenericTypeAnnotation(node)) { const name = node.id.name; if (generics[name]) { @@ -94,27 +84,3 @@ export function removeTypeDuplicates(nodes: Array): Array { return types; } - -/** - * Create a type anotation based on typeof expression. - */ - -export function createTypeAnnotationBasedOnTypeof(type: string) { - if (type === "string") { - return t.stringTypeAnnotation(); - } else if (type === "number") { - return t.numberTypeAnnotation(); - } else if (type === "undefined") { - return t.voidTypeAnnotation(); - } else if (type === "boolean") { - return t.booleanTypeAnnotation(); - } else if (type === "function") { - return t.genericTypeAnnotation(t.identifier("Function")); - } else if (type === "object") { - return t.genericTypeAnnotation(t.identifier("Object")); - } else if (type === "symbol") { - return t.genericTypeAnnotation(t.identifier("Symbol")); - } else { - throw new Error("Invalid typeof value"); - } -} diff --git a/packages/babel-types/src/modifications/inherits.js b/packages/babel-types/src/modifications/inherits.js new file mode 100644 index 0000000000..dba679c050 --- /dev/null +++ b/packages/babel-types/src/modifications/inherits.js @@ -0,0 +1,31 @@ +// @flow +import { INHERIT_KEYS } from "../constants"; +import inheritsComments from "../comments/inheritsComments"; + +/** + * Inherit all contextual properties from `parent` node to `child` node. + */ +export default function inherits(child: T, parent: Object): T { + if (!child || !parent) return child; + + // optionally inherit specific properties if not null + for (const key of (INHERIT_KEYS.optional: Array)) { + if (child[key] == null) { + child[key] = parent[key]; + } + } + + // force inherit "private" properties + for (const key in parent) { + if (key[0] === "_" && key !== "__clone") child[key] = parent[key]; + } + + // force inherit select properties + for (const key of (INHERIT_KEYS.force: Array)) { + child[key] = parent[key]; + } + + inheritsComments(child, parent); + + return child; +} diff --git a/packages/babel-types/src/modifications/prependToMemberExpression.js b/packages/babel-types/src/modifications/prependToMemberExpression.js new file mode 100644 index 0000000000..ce7f4a89f6 --- /dev/null +++ b/packages/babel-types/src/modifications/prependToMemberExpression.js @@ -0,0 +1,14 @@ +// @flow +import { memberExpression } from "../builders/generated"; + +/** + * Prepend a node to a member expression. + */ +export default function prependToMemberExpression( + member: T, + prepend: Object, +): T { + member.object = memberExpression(prepend, member.object); + + return member; +} diff --git a/packages/babel-types/src/modifications/removeProperties.js b/packages/babel-types/src/modifications/removeProperties.js new file mode 100644 index 0000000000..2f81d9cd7e --- /dev/null +++ b/packages/babel-types/src/modifications/removeProperties.js @@ -0,0 +1,31 @@ +// @flow +import { COMMENT_KEYS } from "../constants"; + +const CLEAR_KEYS = ["tokens", "start", "end", "loc", "raw", "rawValue"]; + +const CLEAR_KEYS_PLUS_COMMENTS = COMMENT_KEYS.concat(["comments"]).concat( + CLEAR_KEYS, +); + +/** + * Remove all of the _* properties from a node along with the additional metadata + * properties like location data and raw token data. + */ +export default function removeProperties( + node: Object, + opts?: Object = {}, +): void { + const map = opts.preserveComments ? CLEAR_KEYS : CLEAR_KEYS_PLUS_COMMENTS; + for (const key of map) { + if (node[key] != null) node[key] = undefined; + } + + for (const key in node) { + if (key[0] === "_" && node[key] != null) node[key] = undefined; + } + + const symbols: Array = Object.getOwnPropertySymbols(node); + for (const sym of symbols) { + node[sym] = null; + } +} diff --git a/packages/babel-types/src/modifications/removePropertiesDeep.js b/packages/babel-types/src/modifications/removePropertiesDeep.js new file mode 100644 index 0000000000..fdafc5ca6c --- /dev/null +++ b/packages/babel-types/src/modifications/removePropertiesDeep.js @@ -0,0 +1,12 @@ +// @flow +import traverseFast from "../traverse/traverseFast"; +import removeProperties from "./removeProperties"; + +export default function removePropertiesDeep( + tree: T, + opts?: Object, +): T { + traverseFast(tree, removeProperties, opts); + + return tree; +} diff --git a/packages/babel-types/src/retrievers.js b/packages/babel-types/src/retrievers/getBindingIdentifiers.js similarity index 78% rename from packages/babel-types/src/retrievers.js rename to packages/babel-types/src/retrievers/getBindingIdentifiers.js index 7abdd1f333..d55a6c8326 100644 --- a/packages/babel-types/src/retrievers.js +++ b/packages/babel-types/src/retrievers/getBindingIdentifiers.js @@ -1,14 +1,20 @@ -import * as t from "./index"; +// @flow +import { + isExportDeclaration, + isIdentifier, + isDeclaration, + isFunctionDeclaration, + isFunctionExpression, +} from "../validators/generated"; /** * Return a list of binding identifiers associated with the input `node`. */ - -export function getBindingIdentifiers( +export default function getBindingIdentifiers( node: Object, duplicates?: boolean, outerOnly?: boolean, -): Object { +): { [string]: Object | Array } { let search = [].concat(node); const ids = Object.create(null); @@ -16,9 +22,9 @@ export function getBindingIdentifiers( const id = search.shift(); if (!id) continue; - const keys = t.getBindingIdentifiers.keys[id.type]; + const keys = getBindingIdentifiers.keys[id.type]; - if (t.isIdentifier(id)) { + if (isIdentifier(id)) { if (duplicates) { const _ids = (ids[id.name] = ids[id.name] || []); _ids.push(id); @@ -28,20 +34,20 @@ export function getBindingIdentifiers( continue; } - if (t.isExportDeclaration(id)) { - if (t.isDeclaration(id.declaration)) { + if (isExportDeclaration(id)) { + if (isDeclaration(id.declaration)) { search.push(id.declaration); } continue; } if (outerOnly) { - if (t.isFunctionDeclaration(id)) { + if (isFunctionDeclaration(id)) { search.push(id.id); continue; } - if (t.isFunctionExpression(id)) { + if (isFunctionExpression(id)) { continue; } } @@ -56,13 +62,13 @@ export function getBindingIdentifiers( } } + // $FlowIssue Object.create() seems broken return ids; } /** * Mapping of types to their identifier keys. */ - getBindingIdentifiers.keys = { DeclareClass: ["id"], DeclareFunction: ["id"], @@ -107,10 +113,3 @@ getBindingIdentifiers.keys = { VariableDeclaration: ["declarations"], VariableDeclarator: ["id"], }; - -export function getOuterBindingIdentifiers( - node: Object, - duplicates?: boolean, -): Object { - return getBindingIdentifiers(node, duplicates, true); -} diff --git a/packages/babel-types/src/retrievers/getOuterBindingIdentifiers.js b/packages/babel-types/src/retrievers/getOuterBindingIdentifiers.js new file mode 100644 index 0000000000..caade4b19b --- /dev/null +++ b/packages/babel-types/src/retrievers/getOuterBindingIdentifiers.js @@ -0,0 +1,9 @@ +// @flow +import getBindingIdentifiers from "./getBindingIdentifiers"; + +export default function getOuterBindingIdentifiers( + node: Object, + duplicates?: boolean, +): { [string]: Object | Array } { + return getBindingIdentifiers(node, duplicates, true); +} diff --git a/packages/babel-types/src/traverse.js b/packages/babel-types/src/traverse/traverse.js similarity index 66% rename from packages/babel-types/src/traverse.js rename to packages/babel-types/src/traverse/traverse.js index c4983d1685..3a72d4daa3 100644 --- a/packages/babel-types/src/traverse.js +++ b/packages/babel-types/src/traverse/traverse.js @@ -1,34 +1,5 @@ -import { VISITOR_KEYS } from "./index"; - -/** - * A prefix AST traversal implementation meant for simple searching - * and processing. - */ -export function traverseFast( - node: Node, - enter: (node: Node) => void, - opts?: Object, -) { - if (!node) return; - - const keys = VISITOR_KEYS[node.type]; - if (!keys) return; - - opts = opts || {}; - enter(node, opts); - - for (const key of keys) { - const subNode = node[key]; - - if (Array.isArray(subNode)) { - for (const node of subNode) { - traverseFast(node, enter, opts); - } - } else { - traverseFast(subNode, enter, opts); - } - } -} +// @flow +import { VISITOR_KEYS } from "../definitions"; export type TraversalAncestors = Array<{ node: BabelNode, @@ -46,20 +17,27 @@ export type TraversalHandlers = { * state object. Exposes ancestry data to each handler so that more complex * AST data can be taken into account. */ -export function traverse( +export default function traverse( node: BabelNode, handlers: TraversalHandler | TraversalHandlers, state?: T, -) { +): void { if (typeof handlers === "function") { handlers = { enter: handlers }; } - const { enter, exit } = handlers; + const { enter, exit } = (handlers: TraversalHandlers); traverseSimpleImpl(node, enter, exit, state, []); } -function traverseSimpleImpl(node, enter, exit, state, ancestors) { + +function traverseSimpleImpl( + node: Object, + enter: ?Function, + exit: ?Function, + state: ?T, + ancestors: TraversalAncestors, +) { const keys = VISITOR_KEYS[node.type]; if (!keys) return; diff --git a/packages/babel-types/src/traverse/traverseFast.js b/packages/babel-types/src/traverse/traverseFast.js new file mode 100644 index 0000000000..580628343c --- /dev/null +++ b/packages/babel-types/src/traverse/traverseFast.js @@ -0,0 +1,32 @@ +// @flow +import { VISITOR_KEYS } from "../definitions"; + +/** + * A prefix AST traversal implementation meant for simple searching + * and processing. + */ +export default function traverseFast( + node: Object, + enter: (node: Node, opts?: Object) => void, + opts?: Object, +): void { + if (!node) return; + + const keys = VISITOR_KEYS[node.type]; + if (!keys) return; + + opts = opts || {}; + enter(node, opts); + + for (const key of keys) { + const subNode = node[key]; + + if (Array.isArray(subNode)) { + for (const node of subNode) { + traverseFast(node, enter, opts); + } + } else { + traverseFast(subNode, enter, opts); + } + } +} diff --git a/packages/babel-types/src/utils/inherit.js b/packages/babel-types/src/utils/inherit.js new file mode 100644 index 0000000000..276e0d9143 --- /dev/null +++ b/packages/babel-types/src/utils/inherit.js @@ -0,0 +1,12 @@ +// @flow +import uniq from "lodash/uniq"; + +export default function inherit( + key: string, + child: Object, + parent: Object, +): void { + if (child && parent) { + child[key] = uniq([].concat(child[key], parent[key]).filter(Boolean)); + } +} diff --git a/packages/babel-types/src/react.js b/packages/babel-types/src/utils/react/cleanJSXElementLiteralChild.js similarity index 56% rename from packages/babel-types/src/react.js rename to packages/babel-types/src/utils/react/cleanJSXElementLiteralChild.js index 5abb4fc46d..038782e734 100644 --- a/packages/babel-types/src/react.js +++ b/packages/babel-types/src/utils/react/cleanJSXElementLiteralChild.js @@ -1,12 +1,7 @@ -import * as t from "./index"; +// @flow +import { stringLiteral } from "../../builders/generated"; -export const isReactComponent = t.buildMatchMemberExpression("React.Component"); - -export function isCompatTag(tagName?: string): boolean { - return !!tagName && /^[a-z]|-/.test(tagName); -} - -function cleanJSXElementLiteralChild( +export default function cleanJSXElementLiteralChild( child: { value: string }, args: Array, ) { @@ -51,25 +46,5 @@ function cleanJSXElementLiteralChild( } } - if (str) args.push(t.stringLiteral(str)); -} - -export function buildChildren(node: Object): Array { - const elems = []; - - for (let i = 0; i < node.children.length; i++) { - let child = node.children[i]; - - if (t.isJSXText(child)) { - cleanJSXElementLiteralChild(child, elems); - continue; - } - - if (t.isJSXExpressionContainer(child)) child = child.expression; - if (t.isJSXEmptyExpression(child)) continue; - - elems.push(child); - } - - return elems; + if (str) args.push(stringLiteral(str)); } diff --git a/packages/babel-types/src/utils/shallowEqual.js b/packages/babel-types/src/utils/shallowEqual.js new file mode 100644 index 0000000000..0d4caa46ea --- /dev/null +++ b/packages/babel-types/src/utils/shallowEqual.js @@ -0,0 +1,15 @@ +// @flow +export default function shallowEqual( + actual: Object, + expected: Object, +): boolean { + const keys = Object.keys(expected); + + for (const key of (keys: Array)) { + if (actual[key] !== expected[key]) { + return false; + } + } + + return true; +} diff --git a/packages/babel-types/src/validators.js b/packages/babel-types/src/validators.js deleted file mode 100644 index 5673b01f3e..0000000000 --- a/packages/babel-types/src/validators.js +++ /dev/null @@ -1,316 +0,0 @@ -import { getBindingIdentifiers } from "./retrievers"; -import esutils from "esutils"; -import * as t from "./index"; -import { BLOCK_SCOPED_SYMBOL, RESERVED_WORDS_ES3_ONLY } from "./constants"; - -/** - * Check if the input `node` is a binding identifier. - */ - -export function isBinding(node: Object, parent: Object): boolean { - const keys = getBindingIdentifiers.keys[parent.type]; - if (keys) { - for (let i = 0; i < keys.length; i++) { - const key = keys[i]; - const val = parent[key]; - if (Array.isArray(val)) { - if (val.indexOf(node) >= 0) return true; - } else { - if (val === node) return true; - } - } - } - - return false; -} - -/** - * Check if the input `node` is a reference to a bound variable. - */ - -export function isReferenced(node: Object, parent: Object): boolean { - switch (parent.type) { - // yes: object::NODE - // yes: NODE::callee - case "BindExpression": - return parent.object === node || parent.callee === node; - - // yes: PARENT[NODE] - // yes: NODE.child - // no: parent.NODE - case "MemberExpression": - case "JSXMemberExpression": - if (parent.property === node && parent.computed) { - return true; - } else if (parent.object === node) { - return true; - } else { - return false; - } - - // no: new.NODE - // no: NODE.target - case "MetaProperty": - return false; - - // yes: { [NODE]: "" } - // yes: { NODE } - // no: { NODE: "" } - case "ObjectProperty": - if (parent.key === node) { - return parent.computed; - } - - // no: let NODE = init; - // yes: let id = NODE; - case "VariableDeclarator": - return parent.id !== node; - - // no: function NODE() {} - // no: function foo(NODE) {} - case "ArrowFunctionExpression": - case "FunctionDeclaration": - case "FunctionExpression": - for (const param of (parent.params: Array)) { - if (param === node) return false; - } - - return parent.id !== node; - - // no: export { foo as NODE }; - // yes: export { NODE as foo }; - // no: export { NODE as foo } from "foo"; - case "ExportSpecifier": - if (parent.source) { - return false; - } else { - return parent.local === node; - } - - // no: export NODE from "foo"; - // no: export * as NODE from "foo"; - case "ExportNamespaceSpecifier": - case "ExportDefaultSpecifier": - return false; - - // no:
- case "JSXAttribute": - return parent.name !== node; - - // no: class { NODE = value; } - // yes: class { [NODE] = value; } - // yes: class { key = NODE; } - case "ClassProperty": - if (parent.key === node) { - return parent.computed; - } else { - return parent.value === node; - } - - // no: import NODE from "foo"; - // no: import * as NODE from "foo"; - // no: import { NODE as foo } from "foo"; - // no: import { foo as NODE } from "foo"; - // no: import NODE from "bar"; - case "ImportDefaultSpecifier": - case "ImportNamespaceSpecifier": - case "ImportSpecifier": - return false; - - // no: class NODE {} - case "ClassDeclaration": - case "ClassExpression": - return parent.id !== node; - - // yes: class { [NODE]() {} } - case "ClassMethod": - case "ObjectMethod": - return parent.key === node && parent.computed; - - // no: NODE: for (;;) {} - case "LabeledStatement": - return false; - - // no: try {} catch (NODE) {} - case "CatchClause": - return parent.param !== node; - - // no: function foo(...NODE) {} - case "RestElement": - return false; - - // yes: left = NODE; - // no: NODE = right; - case "AssignmentExpression": - return parent.right === node; - - // no: [NODE = foo] = []; - // yes: [foo = NODE] = []; - case "AssignmentPattern": - return parent.right === node; - - // no: [NODE] = []; - // no: ({ NODE }) = []; - case "ObjectPattern": - case "ArrayPattern": - return false; - } - - return true; -} - -/** - * Check if the input `name` is a valid identifier name - * and isn't a reserved word. - */ - -export function isValidIdentifier(name: string): boolean { - if ( - typeof name !== "string" || - esutils.keyword.isReservedWordES6(name, true) - ) { - return false; - } else if (name === "await") { - // invalid in module, valid in script; better be safe (see #4952) - return false; - } else { - return esutils.keyword.isIdentifierNameES6(name); - } -} -/** - * Check if the input `name` is a valid identifier name according to the ES3 specification. - * - * Additional ES3 reserved words are - */ -export function isValidES3Identifier(name: string): boolean { - return isValidIdentifier(name, true) && !RESERVED_WORDS_ES3_ONLY.has(name); -} - -/** - * Check if the input `node` is a `let` variable declaration. - */ - -export function isLet(node: Object): boolean { - return ( - t.isVariableDeclaration(node) && - (node.kind !== "var" || node[BLOCK_SCOPED_SYMBOL]) - ); -} - -/** - * Check if the input `node` is block scoped. - */ - -export function isBlockScoped(node: Object): boolean { - return ( - t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isLet(node) - ); -} - -/** - * Check if the input `node` is a variable declaration. - */ - -export function isVar(node: Object): boolean { - return ( - t.isVariableDeclaration(node, { kind: "var" }) && !node[BLOCK_SCOPED_SYMBOL] - ); -} - -/** - * Check if the input `specifier` is a `default` import or export. - */ - -export function isSpecifierDefault(specifier: Object): boolean { - return ( - t.isImportDefaultSpecifier(specifier) || - t.isIdentifier(specifier.imported || specifier.exported, { - name: "default", - }) - ); -} - -/** - * Check if the input `node` is a scope. - */ - -export function isScope(node: Object, parent: Object): boolean { - if (t.isBlockStatement(node) && t.isFunction(parent, { body: node })) { - return false; - } - - if (t.isBlockStatement(node) && t.isCatchClause(parent, { body: node })) { - return false; - } - - return t.isScopable(node); -} - -/** - * Check if the input `node` is definitely immutable. - */ - -export function isImmutable(node: Object): boolean { - if (t.isType(node.type, "Immutable")) return true; - - if (t.isIdentifier(node)) { - if (node.name === "undefined") { - // immutable! - return true; - } else { - // no idea... - return false; - } - } - - return false; -} - -/** - * Check if two nodes are equivalent - */ - -export function isNodesEquivalent(a, b) { - if ( - typeof a !== "object" || - typeof b !== "object" || - a == null || - b == null - ) { - return a === b; - } - - if (a.type !== b.type) { - return false; - } - - const fields = Object.keys(t.NODE_FIELDS[a.type] || a.type); - - for (const field of fields) { - if (typeof a[field] !== typeof b[field]) { - return false; - } - - if (Array.isArray(a[field])) { - if (!Array.isArray(b[field])) { - return false; - } - if (a[field].length !== b[field].length) { - return false; - } - - for (let i = 0; i < a[field].length; i++) { - if (!isNodesEquivalent(a[field][i], b[field][i])) { - return false; - } - } - continue; - } - - if (!isNodesEquivalent(a[field], b[field])) { - return false; - } - } - - return true; -} diff --git a/packages/babel-types/src/validators/buildMatchMemberExpression.js b/packages/babel-types/src/validators/buildMatchMemberExpression.js new file mode 100644 index 0000000000..18612de07e --- /dev/null +++ b/packages/babel-types/src/validators/buildMatchMemberExpression.js @@ -0,0 +1,18 @@ +import matchesPattern from "./matchesPattern"; + +/** + * Build a function that when called will return whether or not the + * input `node` `MemberExpression` matches the input `match`. + * + * For example, given the match `React.createClass` it would match the + * parsed nodes of `React.createClass` and `React["createClass"]`. + */ +export default function buildMatchMemberExpression( + match: string, + allowPartial?: boolean, +): Object => boolean { + const parts = match.split("."); + + return (member: Object): boolean => + matchesPattern(member, parts, allowPartial); +} diff --git a/packages/babel-types/src/validators/generated/index.js b/packages/babel-types/src/validators/generated/index.js new file mode 100644 index 0000000000..bae197505a --- /dev/null +++ b/packages/babel-types/src/validators/generated/index.js @@ -0,0 +1,828 @@ +// @flow +/* + * This file is auto-generated! Do not modify it directly. + * To re-generate run 'make build' + */ +import is from "../is"; + +export function isArrayExpression(node: Object, opts?: Object): boolean { + return is("ArrayExpression", node, opts); +} +export function isAssignmentExpression(node: Object, opts?: Object): boolean { + return is("AssignmentExpression", node, opts); +} +export function isBinaryExpression(node: Object, opts?: Object): boolean { + return is("BinaryExpression", node, opts); +} +export function isDirective(node: Object, opts?: Object): boolean { + return is("Directive", node, opts); +} +export function isDirectiveLiteral(node: Object, opts?: Object): boolean { + return is("DirectiveLiteral", node, opts); +} +export function isBlockStatement(node: Object, opts?: Object): boolean { + return is("BlockStatement", node, opts); +} +export function isBreakStatement(node: Object, opts?: Object): boolean { + return is("BreakStatement", node, opts); +} +export function isCallExpression(node: Object, opts?: Object): boolean { + return is("CallExpression", node, opts); +} +export function isCatchClause(node: Object, opts?: Object): boolean { + return is("CatchClause", node, opts); +} +export function isConditionalExpression(node: Object, opts?: Object): boolean { + return is("ConditionalExpression", node, opts); +} +export function isContinueStatement(node: Object, opts?: Object): boolean { + return is("ContinueStatement", node, opts); +} +export function isDebuggerStatement(node: Object, opts?: Object): boolean { + return is("DebuggerStatement", node, opts); +} +export function isDoWhileStatement(node: Object, opts?: Object): boolean { + return is("DoWhileStatement", node, opts); +} +export function isEmptyStatement(node: Object, opts?: Object): boolean { + return is("EmptyStatement", node, opts); +} +export function isExpressionStatement(node: Object, opts?: Object): boolean { + return is("ExpressionStatement", node, opts); +} +export function isFile(node: Object, opts?: Object): boolean { + return is("File", node, opts); +} +export function isForInStatement(node: Object, opts?: Object): boolean { + return is("ForInStatement", node, opts); +} +export function isForStatement(node: Object, opts?: Object): boolean { + return is("ForStatement", node, opts); +} +export function isFunctionDeclaration(node: Object, opts?: Object): boolean { + return is("FunctionDeclaration", node, opts); +} +export function isFunctionExpression(node: Object, opts?: Object): boolean { + return is("FunctionExpression", node, opts); +} +export function isIdentifier(node: Object, opts?: Object): boolean { + return is("Identifier", node, opts); +} +export function isIfStatement(node: Object, opts?: Object): boolean { + return is("IfStatement", node, opts); +} +export function isLabeledStatement(node: Object, opts?: Object): boolean { + return is("LabeledStatement", node, opts); +} +export function isStringLiteral(node: Object, opts?: Object): boolean { + return is("StringLiteral", node, opts); +} +export function isNumericLiteral(node: Object, opts?: Object): boolean { + return is("NumericLiteral", node, opts); +} +export function isNullLiteral(node: Object, opts?: Object): boolean { + return is("NullLiteral", node, opts); +} +export function isBooleanLiteral(node: Object, opts?: Object): boolean { + return is("BooleanLiteral", node, opts); +} +export function isRegExpLiteral(node: Object, opts?: Object): boolean { + return is("RegExpLiteral", node, opts); +} +export function isLogicalExpression(node: Object, opts?: Object): boolean { + return is("LogicalExpression", node, opts); +} +export function isMemberExpression(node: Object, opts?: Object): boolean { + return is("MemberExpression", node, opts); +} +export function isNewExpression(node: Object, opts?: Object): boolean { + return is("NewExpression", node, opts); +} +export function isProgram(node: Object, opts?: Object): boolean { + return is("Program", node, opts); +} +export function isObjectExpression(node: Object, opts?: Object): boolean { + return is("ObjectExpression", node, opts); +} +export function isObjectMethod(node: Object, opts?: Object): boolean { + return is("ObjectMethod", node, opts); +} +export function isObjectProperty(node: Object, opts?: Object): boolean { + return is("ObjectProperty", node, opts); +} +export function isRestElement(node: Object, opts?: Object): boolean { + return is("RestElement", node, opts); +} +export function isReturnStatement(node: Object, opts?: Object): boolean { + return is("ReturnStatement", node, opts); +} +export function isSequenceExpression(node: Object, opts?: Object): boolean { + return is("SequenceExpression", node, opts); +} +export function isSwitchCase(node: Object, opts?: Object): boolean { + return is("SwitchCase", node, opts); +} +export function isSwitchStatement(node: Object, opts?: Object): boolean { + return is("SwitchStatement", node, opts); +} +export function isThisExpression(node: Object, opts?: Object): boolean { + return is("ThisExpression", node, opts); +} +export function isThrowStatement(node: Object, opts?: Object): boolean { + return is("ThrowStatement", node, opts); +} +export function isTryStatement(node: Object, opts?: Object): boolean { + return is("TryStatement", node, opts); +} +export function isUnaryExpression(node: Object, opts?: Object): boolean { + return is("UnaryExpression", node, opts); +} +export function isUpdateExpression(node: Object, opts?: Object): boolean { + return is("UpdateExpression", node, opts); +} +export function isVariableDeclaration(node: Object, opts?: Object): boolean { + return is("VariableDeclaration", node, opts); +} +export function isVariableDeclarator(node: Object, opts?: Object): boolean { + return is("VariableDeclarator", node, opts); +} +export function isWhileStatement(node: Object, opts?: Object): boolean { + return is("WhileStatement", node, opts); +} +export function isWithStatement(node: Object, opts?: Object): boolean { + return is("WithStatement", node, opts); +} +export function isAssignmentPattern(node: Object, opts?: Object): boolean { + return is("AssignmentPattern", node, opts); +} +export function isArrayPattern(node: Object, opts?: Object): boolean { + return is("ArrayPattern", node, opts); +} +export function isArrowFunctionExpression( + node: Object, + opts?: Object, +): boolean { + return is("ArrowFunctionExpression", node, opts); +} +export function isClassBody(node: Object, opts?: Object): boolean { + return is("ClassBody", node, opts); +} +export function isClassDeclaration(node: Object, opts?: Object): boolean { + return is("ClassDeclaration", node, opts); +} +export function isClassExpression(node: Object, opts?: Object): boolean { + return is("ClassExpression", node, opts); +} +export function isExportAllDeclaration(node: Object, opts?: Object): boolean { + return is("ExportAllDeclaration", node, opts); +} +export function isExportDefaultDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("ExportDefaultDeclaration", node, opts); +} +export function isExportNamedDeclaration(node: Object, opts?: Object): boolean { + return is("ExportNamedDeclaration", node, opts); +} +export function isExportSpecifier(node: Object, opts?: Object): boolean { + return is("ExportSpecifier", node, opts); +} +export function isForOfStatement(node: Object, opts?: Object): boolean { + return is("ForOfStatement", node, opts); +} +export function isImportDeclaration(node: Object, opts?: Object): boolean { + return is("ImportDeclaration", node, opts); +} +export function isImportDefaultSpecifier(node: Object, opts?: Object): boolean { + return is("ImportDefaultSpecifier", node, opts); +} +export function isImportNamespaceSpecifier( + node: Object, + opts?: Object, +): boolean { + return is("ImportNamespaceSpecifier", node, opts); +} +export function isImportSpecifier(node: Object, opts?: Object): boolean { + return is("ImportSpecifier", node, opts); +} +export function isMetaProperty(node: Object, opts?: Object): boolean { + return is("MetaProperty", node, opts); +} +export function isClassMethod(node: Object, opts?: Object): boolean { + return is("ClassMethod", node, opts); +} +export function isObjectPattern(node: Object, opts?: Object): boolean { + return is("ObjectPattern", node, opts); +} +export function isSpreadElement(node: Object, opts?: Object): boolean { + return is("SpreadElement", node, opts); +} +export function isSuper(node: Object, opts?: Object): boolean { + return is("Super", node, opts); +} +export function isTaggedTemplateExpression( + node: Object, + opts?: Object, +): boolean { + return is("TaggedTemplateExpression", node, opts); +} +export function isTemplateElement(node: Object, opts?: Object): boolean { + return is("TemplateElement", node, opts); +} +export function isTemplateLiteral(node: Object, opts?: Object): boolean { + return is("TemplateLiteral", node, opts); +} +export function isYieldExpression(node: Object, opts?: Object): boolean { + return is("YieldExpression", node, opts); +} +export function isAnyTypeAnnotation(node: Object, opts?: Object): boolean { + return is("AnyTypeAnnotation", node, opts); +} +export function isArrayTypeAnnotation(node: Object, opts?: Object): boolean { + return is("ArrayTypeAnnotation", node, opts); +} +export function isBooleanTypeAnnotation(node: Object, opts?: Object): boolean { + return is("BooleanTypeAnnotation", node, opts); +} +export function isBooleanLiteralTypeAnnotation( + node: Object, + opts?: Object, +): boolean { + return is("BooleanLiteralTypeAnnotation", node, opts); +} +export function isNullLiteralTypeAnnotation( + node: Object, + opts?: Object, +): boolean { + return is("NullLiteralTypeAnnotation", node, opts); +} +export function isClassImplements(node: Object, opts?: Object): boolean { + return is("ClassImplements", node, opts); +} +export function isDeclareClass(node: Object, opts?: Object): boolean { + return is("DeclareClass", node, opts); +} +export function isDeclareFunction(node: Object, opts?: Object): boolean { + return is("DeclareFunction", node, opts); +} +export function isDeclareInterface(node: Object, opts?: Object): boolean { + return is("DeclareInterface", node, opts); +} +export function isDeclareModule(node: Object, opts?: Object): boolean { + return is("DeclareModule", node, opts); +} +export function isDeclareModuleExports(node: Object, opts?: Object): boolean { + return is("DeclareModuleExports", node, opts); +} +export function isDeclareTypeAlias(node: Object, opts?: Object): boolean { + return is("DeclareTypeAlias", node, opts); +} +export function isDeclareOpaqueType(node: Object, opts?: Object): boolean { + return is("DeclareOpaqueType", node, opts); +} +export function isDeclareVariable(node: Object, opts?: Object): boolean { + return is("DeclareVariable", node, opts); +} +export function isDeclareExportDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("DeclareExportDeclaration", node, opts); +} +export function isDeclareExportAllDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("DeclareExportAllDeclaration", node, opts); +} +export function isDeclaredPredicate(node: Object, opts?: Object): boolean { + return is("DeclaredPredicate", node, opts); +} +export function isExistsTypeAnnotation(node: Object, opts?: Object): boolean { + return is("ExistsTypeAnnotation", node, opts); +} +export function isFunctionTypeAnnotation(node: Object, opts?: Object): boolean { + return is("FunctionTypeAnnotation", node, opts); +} +export function isFunctionTypeParam(node: Object, opts?: Object): boolean { + return is("FunctionTypeParam", node, opts); +} +export function isGenericTypeAnnotation(node: Object, opts?: Object): boolean { + return is("GenericTypeAnnotation", node, opts); +} +export function isInferredPredicate(node: Object, opts?: Object): boolean { + return is("InferredPredicate", node, opts); +} +export function isInterfaceExtends(node: Object, opts?: Object): boolean { + return is("InterfaceExtends", node, opts); +} +export function isInterfaceDeclaration(node: Object, opts?: Object): boolean { + return is("InterfaceDeclaration", node, opts); +} +export function isIntersectionTypeAnnotation( + node: Object, + opts?: Object, +): boolean { + return is("IntersectionTypeAnnotation", node, opts); +} +export function isMixedTypeAnnotation(node: Object, opts?: Object): boolean { + return is("MixedTypeAnnotation", node, opts); +} +export function isEmptyTypeAnnotation(node: Object, opts?: Object): boolean { + return is("EmptyTypeAnnotation", node, opts); +} +export function isNullableTypeAnnotation(node: Object, opts?: Object): boolean { + return is("NullableTypeAnnotation", node, opts); +} +export function isNumberLiteralTypeAnnotation( + node: Object, + opts?: Object, +): boolean { + return is("NumberLiteralTypeAnnotation", node, opts); +} +export function isNumberTypeAnnotation(node: Object, opts?: Object): boolean { + return is("NumberTypeAnnotation", node, opts); +} +export function isObjectTypeAnnotation(node: Object, opts?: Object): boolean { + return is("ObjectTypeAnnotation", node, opts); +} +export function isObjectTypeCallProperty(node: Object, opts?: Object): boolean { + return is("ObjectTypeCallProperty", node, opts); +} +export function isObjectTypeIndexer(node: Object, opts?: Object): boolean { + return is("ObjectTypeIndexer", node, opts); +} +export function isObjectTypeProperty(node: Object, opts?: Object): boolean { + return is("ObjectTypeProperty", node, opts); +} +export function isObjectTypeSpreadProperty( + node: Object, + opts?: Object, +): boolean { + return is("ObjectTypeSpreadProperty", node, opts); +} +export function isOpaqueType(node: Object, opts?: Object): boolean { + return is("OpaqueType", node, opts); +} +export function isQualifiedTypeIdentifier( + node: Object, + opts?: Object, +): boolean { + return is("QualifiedTypeIdentifier", node, opts); +} +export function isStringLiteralTypeAnnotation( + node: Object, + opts?: Object, +): boolean { + return is("StringLiteralTypeAnnotation", node, opts); +} +export function isStringTypeAnnotation(node: Object, opts?: Object): boolean { + return is("StringTypeAnnotation", node, opts); +} +export function isThisTypeAnnotation(node: Object, opts?: Object): boolean { + return is("ThisTypeAnnotation", node, opts); +} +export function isTupleTypeAnnotation(node: Object, opts?: Object): boolean { + return is("TupleTypeAnnotation", node, opts); +} +export function isTypeofTypeAnnotation(node: Object, opts?: Object): boolean { + return is("TypeofTypeAnnotation", node, opts); +} +export function isTypeAlias(node: Object, opts?: Object): boolean { + return is("TypeAlias", node, opts); +} +export function isTypeAnnotation(node: Object, opts?: Object): boolean { + return is("TypeAnnotation", node, opts); +} +export function isTypeCastExpression(node: Object, opts?: Object): boolean { + return is("TypeCastExpression", node, opts); +} +export function isTypeParameter(node: Object, opts?: Object): boolean { + return is("TypeParameter", node, opts); +} +export function isTypeParameterDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("TypeParameterDeclaration", node, opts); +} +export function isTypeParameterInstantiation( + node: Object, + opts?: Object, +): boolean { + return is("TypeParameterInstantiation", node, opts); +} +export function isUnionTypeAnnotation(node: Object, opts?: Object): boolean { + return is("UnionTypeAnnotation", node, opts); +} +export function isVoidTypeAnnotation(node: Object, opts?: Object): boolean { + return is("VoidTypeAnnotation", node, opts); +} +export function isJSXAttribute(node: Object, opts?: Object): boolean { + return is("JSXAttribute", node, opts); +} +export function isJSXClosingElement(node: Object, opts?: Object): boolean { + return is("JSXClosingElement", node, opts); +} +export function isJSXElement(node: Object, opts?: Object): boolean { + return is("JSXElement", node, opts); +} +export function isJSXEmptyExpression(node: Object, opts?: Object): boolean { + return is("JSXEmptyExpression", node, opts); +} +export function isJSXExpressionContainer(node: Object, opts?: Object): boolean { + return is("JSXExpressionContainer", node, opts); +} +export function isJSXSpreadChild(node: Object, opts?: Object): boolean { + return is("JSXSpreadChild", node, opts); +} +export function isJSXIdentifier(node: Object, opts?: Object): boolean { + return is("JSXIdentifier", node, opts); +} +export function isJSXMemberExpression(node: Object, opts?: Object): boolean { + return is("JSXMemberExpression", node, opts); +} +export function isJSXNamespacedName(node: Object, opts?: Object): boolean { + return is("JSXNamespacedName", node, opts); +} +export function isJSXOpeningElement(node: Object, opts?: Object): boolean { + return is("JSXOpeningElement", node, opts); +} +export function isJSXSpreadAttribute(node: Object, opts?: Object): boolean { + return is("JSXSpreadAttribute", node, opts); +} +export function isJSXText(node: Object, opts?: Object): boolean { + return is("JSXText", node, opts); +} +export function isJSXFragment(node: Object, opts?: Object): boolean { + return is("JSXFragment", node, opts); +} +export function isJSXOpeningFragment(node: Object, opts?: Object): boolean { + return is("JSXOpeningFragment", node, opts); +} +export function isJSXClosingFragment(node: Object, opts?: Object): boolean { + return is("JSXClosingFragment", node, opts); +} +export function isNoop(node: Object, opts?: Object): boolean { + return is("Noop", node, opts); +} +export function isParenthesizedExpression( + node: Object, + opts?: Object, +): boolean { + return is("ParenthesizedExpression", node, opts); +} +export function isAwaitExpression(node: Object, opts?: Object): boolean { + return is("AwaitExpression", node, opts); +} +export function isBindExpression(node: Object, opts?: Object): boolean { + return is("BindExpression", node, opts); +} +export function isClassProperty(node: Object, opts?: Object): boolean { + return is("ClassProperty", node, opts); +} +export function isImport(node: Object, opts?: Object): boolean { + return is("Import", node, opts); +} +export function isDecorator(node: Object, opts?: Object): boolean { + return is("Decorator", node, opts); +} +export function isDoExpression(node: Object, opts?: Object): boolean { + return is("DoExpression", node, opts); +} +export function isExportDefaultSpecifier(node: Object, opts?: Object): boolean { + return is("ExportDefaultSpecifier", node, opts); +} +export function isExportNamespaceSpecifier( + node: Object, + opts?: Object, +): boolean { + return is("ExportNamespaceSpecifier", node, opts); +} +export function isTSParameterProperty(node: Object, opts?: Object): boolean { + return is("TSParameterProperty", node, opts); +} +export function isTSDeclareFunction(node: Object, opts?: Object): boolean { + return is("TSDeclareFunction", node, opts); +} +export function isTSDeclareMethod(node: Object, opts?: Object): boolean { + return is("TSDeclareMethod", node, opts); +} +export function isTSQualifiedName(node: Object, opts?: Object): boolean { + return is("TSQualifiedName", node, opts); +} +export function isTSCallSignatureDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("TSCallSignatureDeclaration", node, opts); +} +export function isTSConstructSignatureDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("TSConstructSignatureDeclaration", node, opts); +} +export function isTSPropertySignature(node: Object, opts?: Object): boolean { + return is("TSPropertySignature", node, opts); +} +export function isTSMethodSignature(node: Object, opts?: Object): boolean { + return is("TSMethodSignature", node, opts); +} +export function isTSIndexSignature(node: Object, opts?: Object): boolean { + return is("TSIndexSignature", node, opts); +} +export function isTSAnyKeyword(node: Object, opts?: Object): boolean { + return is("TSAnyKeyword", node, opts); +} +export function isTSNumberKeyword(node: Object, opts?: Object): boolean { + return is("TSNumberKeyword", node, opts); +} +export function isTSObjectKeyword(node: Object, opts?: Object): boolean { + return is("TSObjectKeyword", node, opts); +} +export function isTSBooleanKeyword(node: Object, opts?: Object): boolean { + return is("TSBooleanKeyword", node, opts); +} +export function isTSStringKeyword(node: Object, opts?: Object): boolean { + return is("TSStringKeyword", node, opts); +} +export function isTSSymbolKeyword(node: Object, opts?: Object): boolean { + return is("TSSymbolKeyword", node, opts); +} +export function isTSVoidKeyword(node: Object, opts?: Object): boolean { + return is("TSVoidKeyword", node, opts); +} +export function isTSUndefinedKeyword(node: Object, opts?: Object): boolean { + return is("TSUndefinedKeyword", node, opts); +} +export function isTSNullKeyword(node: Object, opts?: Object): boolean { + return is("TSNullKeyword", node, opts); +} +export function isTSNeverKeyword(node: Object, opts?: Object): boolean { + return is("TSNeverKeyword", node, opts); +} +export function isTSThisType(node: Object, opts?: Object): boolean { + return is("TSThisType", node, opts); +} +export function isTSFunctionType(node: Object, opts?: Object): boolean { + return is("TSFunctionType", node, opts); +} +export function isTSConstructorType(node: Object, opts?: Object): boolean { + return is("TSConstructorType", node, opts); +} +export function isTSTypeReference(node: Object, opts?: Object): boolean { + return is("TSTypeReference", node, opts); +} +export function isTSTypePredicate(node: Object, opts?: Object): boolean { + return is("TSTypePredicate", node, opts); +} +export function isTSTypeQuery(node: Object, opts?: Object): boolean { + return is("TSTypeQuery", node, opts); +} +export function isTSTypeLiteral(node: Object, opts?: Object): boolean { + return is("TSTypeLiteral", node, opts); +} +export function isTSArrayType(node: Object, opts?: Object): boolean { + return is("TSArrayType", node, opts); +} +export function isTSTupleType(node: Object, opts?: Object): boolean { + return is("TSTupleType", node, opts); +} +export function isTSUnionType(node: Object, opts?: Object): boolean { + return is("TSUnionType", node, opts); +} +export function isTSIntersectionType(node: Object, opts?: Object): boolean { + return is("TSIntersectionType", node, opts); +} +export function isTSParenthesizedType(node: Object, opts?: Object): boolean { + return is("TSParenthesizedType", node, opts); +} +export function isTSTypeOperator(node: Object, opts?: Object): boolean { + return is("TSTypeOperator", node, opts); +} +export function isTSIndexedAccessType(node: Object, opts?: Object): boolean { + return is("TSIndexedAccessType", node, opts); +} +export function isTSMappedType(node: Object, opts?: Object): boolean { + return is("TSMappedType", node, opts); +} +export function isTSLiteralType(node: Object, opts?: Object): boolean { + return is("TSLiteralType", node, opts); +} +export function isTSExpressionWithTypeArguments( + node: Object, + opts?: Object, +): boolean { + return is("TSExpressionWithTypeArguments", node, opts); +} +export function isTSInterfaceDeclaration(node: Object, opts?: Object): boolean { + return is("TSInterfaceDeclaration", node, opts); +} +export function isTSInterfaceBody(node: Object, opts?: Object): boolean { + return is("TSInterfaceBody", node, opts); +} +export function isTSTypeAliasDeclaration(node: Object, opts?: Object): boolean { + return is("TSTypeAliasDeclaration", node, opts); +} +export function isTSAsExpression(node: Object, opts?: Object): boolean { + return is("TSAsExpression", node, opts); +} +export function isTSTypeAssertion(node: Object, opts?: Object): boolean { + return is("TSTypeAssertion", node, opts); +} +export function isTSEnumDeclaration(node: Object, opts?: Object): boolean { + return is("TSEnumDeclaration", node, opts); +} +export function isTSEnumMember(node: Object, opts?: Object): boolean { + return is("TSEnumMember", node, opts); +} +export function isTSModuleDeclaration(node: Object, opts?: Object): boolean { + return is("TSModuleDeclaration", node, opts); +} +export function isTSModuleBlock(node: Object, opts?: Object): boolean { + return is("TSModuleBlock", node, opts); +} +export function isTSImportEqualsDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("TSImportEqualsDeclaration", node, opts); +} +export function isTSExternalModuleReference( + node: Object, + opts?: Object, +): boolean { + return is("TSExternalModuleReference", node, opts); +} +export function isTSNonNullExpression(node: Object, opts?: Object): boolean { + return is("TSNonNullExpression", node, opts); +} +export function isTSExportAssignment(node: Object, opts?: Object): boolean { + return is("TSExportAssignment", node, opts); +} +export function isTSNamespaceExportDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("TSNamespaceExportDeclaration", node, opts); +} +export function isTSTypeAnnotation(node: Object, opts?: Object): boolean { + return is("TSTypeAnnotation", node, opts); +} +export function isTSTypeParameterInstantiation( + node: Object, + opts?: Object, +): boolean { + return is("TSTypeParameterInstantiation", node, opts); +} +export function isTSTypeParameterDeclaration( + node: Object, + opts?: Object, +): boolean { + return is("TSTypeParameterDeclaration", node, opts); +} +export function isTSTypeParameter(node: Object, opts?: Object): boolean { + return is("TSTypeParameter", node, opts); +} +export function isExpression(node: Object, opts?: Object): boolean { + return is("Expression", node, opts); +} +export function isBinary(node: Object, opts?: Object): boolean { + return is("Binary", node, opts); +} +export function isScopable(node: Object, opts?: Object): boolean { + return is("Scopable", node, opts); +} +export function isBlockParent(node: Object, opts?: Object): boolean { + return is("BlockParent", node, opts); +} +export function isBlock(node: Object, opts?: Object): boolean { + return is("Block", node, opts); +} +export function isStatement(node: Object, opts?: Object): boolean { + return is("Statement", node, opts); +} +export function isTerminatorless(node: Object, opts?: Object): boolean { + return is("Terminatorless", node, opts); +} +export function isCompletionStatement(node: Object, opts?: Object): boolean { + return is("CompletionStatement", node, opts); +} +export function isConditional(node: Object, opts?: Object): boolean { + return is("Conditional", node, opts); +} +export function isLoop(node: Object, opts?: Object): boolean { + return is("Loop", node, opts); +} +export function isWhile(node: Object, opts?: Object): boolean { + return is("While", node, opts); +} +export function isExpressionWrapper(node: Object, opts?: Object): boolean { + return is("ExpressionWrapper", node, opts); +} +export function isFor(node: Object, opts?: Object): boolean { + return is("For", node, opts); +} +export function isForXStatement(node: Object, opts?: Object): boolean { + return is("ForXStatement", node, opts); +} +export function isFunction(node: Object, opts?: Object): boolean { + return is("Function", node, opts); +} +export function isFunctionParent(node: Object, opts?: Object): boolean { + return is("FunctionParent", node, opts); +} +export function isPureish(node: Object, opts?: Object): boolean { + return is("Pureish", node, opts); +} +export function isDeclaration(node: Object, opts?: Object): boolean { + return is("Declaration", node, opts); +} +export function isPatternLike(node: Object, opts?: Object): boolean { + return is("PatternLike", node, opts); +} +export function isLVal(node: Object, opts?: Object): boolean { + return is("LVal", node, opts); +} +export function isTSEntityName(node: Object, opts?: Object): boolean { + return is("TSEntityName", node, opts); +} +export function isLiteral(node: Object, opts?: Object): boolean { + return is("Literal", node, opts); +} +export function isImmutable(node: Object, opts?: Object): boolean { + return is("Immutable", node, opts); +} +export function isUserWhitespacable(node: Object, opts?: Object): boolean { + return is("UserWhitespacable", node, opts); +} +export function isMethod(node: Object, opts?: Object): boolean { + return is("Method", node, opts); +} +export function isObjectMember(node: Object, opts?: Object): boolean { + return is("ObjectMember", node, opts); +} +export function isProperty(node: Object, opts?: Object): boolean { + return is("Property", node, opts); +} +export function isUnaryLike(node: Object, opts?: Object): boolean { + return is("UnaryLike", node, opts); +} +export function isPattern(node: Object, opts?: Object): boolean { + return is("Pattern", node, opts); +} +export function isClass(node: Object, opts?: Object): boolean { + return is("Class", node, opts); +} +export function isModuleDeclaration(node: Object, opts?: Object): boolean { + return is("ModuleDeclaration", node, opts); +} +export function isExportDeclaration(node: Object, opts?: Object): boolean { + return is("ExportDeclaration", node, opts); +} +export function isModuleSpecifier(node: Object, opts?: Object): boolean { + return is("ModuleSpecifier", node, opts); +} +export function isFlow(node: Object, opts?: Object): boolean { + return is("Flow", node, opts); +} +export function isFlowBaseAnnotation(node: Object, opts?: Object): boolean { + return is("FlowBaseAnnotation", node, opts); +} +export function isFlowDeclaration(node: Object, opts?: Object): boolean { + return is("FlowDeclaration", node, opts); +} +export function isFlowPredicate(node: Object, opts?: Object): boolean { + return is("FlowPredicate", node, opts); +} +export function isJSX(node: Object, opts?: Object): boolean { + return is("JSX", node, opts); +} +export function isTSTypeElement(node: Object, opts?: Object): boolean { + return is("TSTypeElement", node, opts); +} +export function isTSType(node: Object, opts?: Object): boolean { + return is("TSType", node, opts); +} +export function isNumberLiteral(node: Object, opts: Object): boolean { + console.trace( + "The node type NumberLiteral has been renamed to NumericLiteral", + ); + return is("NumberLiteral", node, opts); +} +export function isRegexLiteral(node: Object, opts: Object): boolean { + console.trace("The node type RegexLiteral has been renamed to RegExpLiteral"); + return is("RegexLiteral", node, opts); +} +export function isRestProperty(node: Object, opts: Object): boolean { + console.trace("The node type RestProperty has been renamed to RestElement"); + return is("RestProperty", node, opts); +} +export function isSpreadProperty(node: Object, opts: Object): boolean { + console.trace( + "The node type SpreadProperty has been renamed to SpreadElement", + ); + return is("SpreadProperty", node, opts); +} diff --git a/packages/babel-types/src/validators/is.js b/packages/babel-types/src/validators/is.js new file mode 100644 index 0000000000..c5db6a4fcf --- /dev/null +++ b/packages/babel-types/src/validators/is.js @@ -0,0 +1,22 @@ +// @flow +import shallowEqual from "../utils/shallowEqual"; +import isType from "./isType"; + +/** + * Returns whether `node` is of given `type`. + * + * For better performance, use this instead of `is[Type]` when `type` is unknown. + * Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`. + */ +export default function is(type: string, node: Object, opts?: Object): boolean { + if (!node) return false; + + const matches = isType(node.type, type); + if (!matches) return false; + + if (typeof opts === "undefined") { + return true; + } else { + return shallowEqual(node, opts); + } +} diff --git a/packages/babel-types/src/validators/isBinding.js b/packages/babel-types/src/validators/isBinding.js new file mode 100644 index 0000000000..b1719a3b38 --- /dev/null +++ b/packages/babel-types/src/validators/isBinding.js @@ -0,0 +1,21 @@ +// @flow +import getBindingIdentifiers from "../retrievers/getBindingIdentifiers"; +/** + * Check if the input `node` is a binding identifier. + */ +export default function isBinding(node: Object, parent: Object): boolean { + const keys = getBindingIdentifiers.keys[parent.type]; + if (keys) { + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const val = parent[key]; + if (Array.isArray(val)) { + if (val.indexOf(node) >= 0) return true; + } else { + if (val === node) return true; + } + } + } + + return false; +} diff --git a/packages/babel-types/src/validators/isBlockScoped.js b/packages/babel-types/src/validators/isBlockScoped.js new file mode 100644 index 0000000000..51ae6e0749 --- /dev/null +++ b/packages/babel-types/src/validators/isBlockScoped.js @@ -0,0 +1,10 @@ +// @flow +import { isClassDeclaration, isFunctionDeclaration } from "./generated"; +import isLet from "./isLet"; + +/** + * Check if the input `node` is block scoped. + */ +export default function isBlockScoped(node: Object): boolean { + return isFunctionDeclaration(node) || isClassDeclaration(node) || isLet(node); +} diff --git a/packages/babel-types/src/validators/isImmutable.js b/packages/babel-types/src/validators/isImmutable.js new file mode 100644 index 0000000000..d4d049c583 --- /dev/null +++ b/packages/babel-types/src/validators/isImmutable.js @@ -0,0 +1,22 @@ +// @flow +import isType from "./isType"; +import { isIdentifier } from "./generated"; + +/** + * Check if the input `node` is definitely immutable. + */ +export default function isImmutable(node: Object): boolean { + if (isType(node.type, "Immutable")) return true; + + if (isIdentifier(node)) { + if (node.name === "undefined") { + // immutable! + return true; + } else { + // no idea... + return false; + } + } + + return false; +} diff --git a/packages/babel-types/src/validators/isLet.js b/packages/babel-types/src/validators/isLet.js new file mode 100644 index 0000000000..a8c48182f1 --- /dev/null +++ b/packages/babel-types/src/validators/isLet.js @@ -0,0 +1,13 @@ +// @flow +import { isVariableDeclaration } from "./generated"; +import { BLOCK_SCOPED_SYMBOL } from "../constants"; + +/** + * Check if the input `node` is a `let` variable declaration. + */ +export default function isLet(node: Object): boolean { + return ( + isVariableDeclaration(node) && + (node.kind !== "var" || node[BLOCK_SCOPED_SYMBOL]) + ); +} diff --git a/packages/babel-types/src/validators/isNode.js b/packages/babel-types/src/validators/isNode.js new file mode 100644 index 0000000000..afa11190fa --- /dev/null +++ b/packages/babel-types/src/validators/isNode.js @@ -0,0 +1,6 @@ +// @flow +import { VISITOR_KEYS } from "../definitions"; + +export default function isNode(node?: Object): boolean { + return !!(node && VISITOR_KEYS[node.type]); +} diff --git a/packages/babel-types/src/validators/isNodesEquivalent.js b/packages/babel-types/src/validators/isNodesEquivalent.js new file mode 100644 index 0000000000..ab689f5693 --- /dev/null +++ b/packages/babel-types/src/validators/isNodesEquivalent.js @@ -0,0 +1,50 @@ +// @flow +import { NODE_FIELDS } from "../definitions"; + +/** + * Check if two nodes are equivalent + */ +export default function isNodesEquivalent(a: any, b: any): boolean { + if ( + typeof a !== "object" || + typeof b !== "object" || + a == null || + b == null + ) { + return a === b; + } + + if (a.type !== b.type) { + return false; + } + + const fields = Object.keys(NODE_FIELDS[a.type] || a.type); + + for (const field of fields) { + if (typeof a[field] !== typeof b[field]) { + return false; + } + + if (Array.isArray(a[field])) { + if (!Array.isArray(b[field])) { + return false; + } + if (a[field].length !== b[field].length) { + return false; + } + + for (let i = 0; i < a[field].length; i++) { + if (!isNodesEquivalent(a[field][i], b[field][i])) { + return false; + } + } + continue; + } + + if (!isNodesEquivalent(a[field], b[field])) { + return false; + } + } + + return true; +} diff --git a/packages/babel-types/src/validators/isReferenced.js b/packages/babel-types/src/validators/isReferenced.js new file mode 100644 index 0000000000..e9519862a4 --- /dev/null +++ b/packages/babel-types/src/validators/isReferenced.js @@ -0,0 +1,134 @@ +// @flow +/** + * Check if the input `node` is a reference to a bound variable. + */ +export default function isReferenced(node: Object, parent: Object): boolean { + switch (parent.type) { + // yes: object::NODE + // yes: NODE::callee + case "BindExpression": + return parent.object === node || parent.callee === node; + + // yes: PARENT[NODE] + // yes: NODE.child + // no: parent.NODE + case "MemberExpression": + case "JSXMemberExpression": + if (parent.property === node && parent.computed) { + return true; + } else if (parent.object === node) { + return true; + } else { + return false; + } + + // no: new.NODE + // no: NODE.target + case "MetaProperty": + return false; + + // yes: { [NODE]: "" } + // yes: { NODE } + // no: { NODE: "" } + case "ObjectProperty": + if (parent.key === node) { + return parent.computed; + } + + // no: let NODE = init; + // yes: let id = NODE; + case "VariableDeclarator": + return parent.id !== node; + + // no: function NODE() {} + // no: function foo(NODE) {} + case "ArrowFunctionExpression": + case "FunctionDeclaration": + case "FunctionExpression": + for (const param of (parent.params: Array)) { + if (param === node) return false; + } + + return parent.id !== node; + + // no: export { foo as NODE }; + // yes: export { NODE as foo }; + // no: export { NODE as foo } from "foo"; + case "ExportSpecifier": + if (parent.source) { + return false; + } else { + return parent.local === node; + } + + // no: export NODE from "foo"; + // no: export * as NODE from "foo"; + case "ExportNamespaceSpecifier": + case "ExportDefaultSpecifier": + return false; + + // no:
+ case "JSXAttribute": + return parent.name !== node; + + // no: class { NODE = value; } + // yes: class { [NODE] = value; } + // yes: class { key = NODE; } + case "ClassProperty": + if (parent.key === node) { + return parent.computed; + } else { + return parent.value === node; + } + + // no: import NODE from "foo"; + // no: import * as NODE from "foo"; + // no: import { NODE as foo } from "foo"; + // no: import { foo as NODE } from "foo"; + // no: import NODE from "bar"; + case "ImportDefaultSpecifier": + case "ImportNamespaceSpecifier": + case "ImportSpecifier": + return false; + + // no: class NODE {} + case "ClassDeclaration": + case "ClassExpression": + return parent.id !== node; + + // yes: class { [NODE]() {} } + case "ClassMethod": + case "ObjectMethod": + return parent.key === node && parent.computed; + + // no: NODE: for (;;) {} + case "LabeledStatement": + return false; + + // no: try {} catch (NODE) {} + case "CatchClause": + return parent.param !== node; + + // no: function foo(...NODE) {} + case "RestElement": + return false; + + // yes: left = NODE; + // no: NODE = right; + case "AssignmentExpression": + return parent.right === node; + + // no: [NODE = foo] = []; + // yes: [foo = NODE] = []; + case "AssignmentPattern": + return parent.right === node; + + // no: [NODE] = []; + // no: ({ NODE }) = []; + case "ObjectPattern": + case "ArrayPattern": + return false; + } + + return true; +} diff --git a/packages/babel-types/src/validators/isScope.js b/packages/babel-types/src/validators/isScope.js new file mode 100644 index 0000000000..51d6c91924 --- /dev/null +++ b/packages/babel-types/src/validators/isScope.js @@ -0,0 +1,22 @@ +// @flow +import { + isFunction, + isCatchClause, + isBlockStatement, + isScopable, +} from "./generated"; + +/** + * Check if the input `node` is a scope. + */ +export default function isScope(node: Object, parent: Object): boolean { + if (isBlockStatement(node) && isFunction(parent, { body: node })) { + return false; + } + + if (isBlockStatement(node) && isCatchClause(parent, { body: node })) { + return false; + } + + return isScopable(node); +} diff --git a/packages/babel-types/src/validators/isSpecifierDefault.js b/packages/babel-types/src/validators/isSpecifierDefault.js new file mode 100644 index 0000000000..13fbe0fcb3 --- /dev/null +++ b/packages/babel-types/src/validators/isSpecifierDefault.js @@ -0,0 +1,14 @@ +// @flow +import { isIdentifier, isImportDefaultSpecifier } from "./generated"; + +/** + * Check if the input `specifier` is a `default` import or export. + */ +export default function isSpecifierDefault(specifier: Object): boolean { + return ( + isImportDefaultSpecifier(specifier) || + isIdentifier(specifier.imported || specifier.exported, { + name: "default", + }) + ); +} diff --git a/packages/babel-types/src/validators/isType.js b/packages/babel-types/src/validators/isType.js new file mode 100644 index 0000000000..6b5e0feade --- /dev/null +++ b/packages/babel-types/src/validators/isType.js @@ -0,0 +1,24 @@ +// @flow +import { FLIPPED_ALIAS_KEYS, ALIAS_KEYS } from "../definitions"; + +/** + * Test if a `nodeType` is a `targetType` or if `targetType` is an alias of `nodeType`. + */ +export default function isType(nodeType: string, targetType: string): boolean { + if (nodeType === targetType) return true; + + // This is a fast-path. If the test above failed, but an alias key is found, then the + // targetType was a primary node type, so there's no need to check the aliases. + if (ALIAS_KEYS[targetType]) return false; + + const aliases: ?Array = FLIPPED_ALIAS_KEYS[targetType]; + if (aliases) { + if (aliases[0] === nodeType) return true; + + for (const alias of aliases) { + if (nodeType === alias) return true; + } + } + + return false; +} diff --git a/packages/babel-types/src/validators/isValidES3Identifier.js b/packages/babel-types/src/validators/isValidES3Identifier.js new file mode 100644 index 0000000000..3d34a12fea --- /dev/null +++ b/packages/babel-types/src/validators/isValidES3Identifier.js @@ -0,0 +1,38 @@ +// @flow +import isValidIdentifier from "./isValidIdentifier"; + +const RESERVED_WORDS_ES3_ONLY: Set = new Set([ + "abstract", + "boolean", + "byte", + "char", + "double", + "enum", + "final", + "float", + "goto", + "implements", + "int", + "interface", + "long", + "native", + "package", + "private", + "protected", + "public", + "short", + "static", + "synchronized", + "throws", + "transient", + "volatile", +]); + +/** + * Check if the input `name` is a valid identifier name according to the ES3 specification. + * + * Additional ES3 reserved words are + */ +export default function isValidES3Identifier(name: string): boolean { + return isValidIdentifier(name) && !RESERVED_WORDS_ES3_ONLY.has(name); +} diff --git a/packages/babel-types/src/validators/isValidIdentifier.js b/packages/babel-types/src/validators/isValidIdentifier.js new file mode 100644 index 0000000000..6dbbb7c32c --- /dev/null +++ b/packages/babel-types/src/validators/isValidIdentifier.js @@ -0,0 +1,20 @@ +// @flow +import esutils from "esutils"; + +/** + * Check if the input `name` is a valid identifier name + * and isn't a reserved word. + */ +export default function isValidIdentifier(name: string): boolean { + if ( + typeof name !== "string" || + esutils.keyword.isReservedWordES6(name, true) + ) { + return false; + } else if (name === "await") { + // invalid in module, valid in script; better be safe (see #4952) + return false; + } else { + return esutils.keyword.isIdentifierNameES6(name); + } +} diff --git a/packages/babel-types/src/validators/isVar.js b/packages/babel-types/src/validators/isVar.js new file mode 100644 index 0000000000..98eb627265 --- /dev/null +++ b/packages/babel-types/src/validators/isVar.js @@ -0,0 +1,12 @@ +// @flow +import { isVariableDeclaration } from "./generated"; +import { BLOCK_SCOPED_SYMBOL } from "../constants"; + +/** + * Check if the input `node` is a variable declaration. + */ +export default function isVar(node: Object): boolean { + return ( + isVariableDeclaration(node, { kind: "var" }) && !node[BLOCK_SCOPED_SYMBOL] + ); +} diff --git a/packages/babel-types/src/validators/matchesPattern.js b/packages/babel-types/src/validators/matchesPattern.js new file mode 100644 index 0000000000..4c7ff9d781 --- /dev/null +++ b/packages/babel-types/src/validators/matchesPattern.js @@ -0,0 +1,45 @@ +import { isIdentifier, isMemberExpression, isStringLiteral } from "./generated"; + +/** + * Determines whether or not the input node `member` matches the + * input `match`. + * + * For example, given the match `React.createClass` it would match the + * parsed nodes of `React.createClass` and `React["createClass"]`. + */ +export default function matchesPattern( + member: Object, + match: string | Array, + allowPartial?: boolean, +): boolean { + // not a member expression + if (!isMemberExpression(member)) return false; + + const parts = Array.isArray(match) ? match : match.split("."); + const nodes = []; + + let node; + for (node = member; isMemberExpression(node); node = node.object) { + nodes.push(node.property); + } + nodes.push(node); + + if (nodes.length < parts.length) return false; + if (!allowPartial && nodes.length > parts.length) return false; + + for (let i = 0, j = nodes.length - 1; i < parts.length; i++, j--) { + const node = nodes[j]; + let value; + if (isIdentifier(node)) { + value = node.name; + } else if (isStringLiteral(node)) { + value = node.value; + } else { + return false; + } + + if (parts[i] !== value) return false; + } + + return true; +} diff --git a/packages/babel-types/src/validators/react/isCompatTag.js b/packages/babel-types/src/validators/react/isCompatTag.js new file mode 100644 index 0000000000..283d1ca7cc --- /dev/null +++ b/packages/babel-types/src/validators/react/isCompatTag.js @@ -0,0 +1,4 @@ +// @flow +export default function isCompatTag(tagName?: string): boolean { + return !!tagName && /^[a-z]|-/.test(tagName); +} diff --git a/packages/babel-types/src/validators/react/isReactComponent.js b/packages/babel-types/src/validators/react/isReactComponent.js new file mode 100644 index 0000000000..6f91769843 --- /dev/null +++ b/packages/babel-types/src/validators/react/isReactComponent.js @@ -0,0 +1,6 @@ +// @flow +import buildMatchMemberExpression from "../buildMatchMemberExpression"; + +const isReactComponent = buildMatchMemberExpression("React.Component"); + +export default isReactComponent; diff --git a/packages/babel-types/src/validators/validate.js b/packages/babel-types/src/validators/validate.js new file mode 100644 index 0000000000..9b2e9a8cd0 --- /dev/null +++ b/packages/babel-types/src/validators/validate.js @@ -0,0 +1,15 @@ +// @flow +import { NODE_FIELDS } from "../definitions"; + +export default function validate(node?: Object, key: string, val: any): void { + if (!node) return; + + const fields = NODE_FIELDS[node.type]; + if (!fields) return; + + const field = fields[key]; + if (!field || !field.validate) return; + if (field.optional && val == null) return; + + field.validate(node, key, val); +}