From 98ca541fde0c1ec9f2b5e5222e0adf08740cb540 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 11 Mar 2015 00:04:06 +1100 Subject: [PATCH] restructure types --- .../generation/generators/expressions.js | 2 +- src/babel/generation/generators/flow.js | 2 +- src/babel/generation/generators/jsx.js | 2 +- src/babel/generation/generators/methods.js | 2 +- src/babel/generation/generators/modules.js | 2 +- src/babel/generation/generators/statements.js | 2 +- src/babel/generation/index.js | 2 +- src/babel/generation/node/index.js | 2 +- src/babel/generation/node/parentheses.js | 2 +- src/babel/generation/node/whitespace.js | 2 +- src/babel/generation/source-map.js | 2 +- src/babel/helpers/normalize-ast.js | 2 +- src/babel/patch.js | 2 +- src/babel/tools/build-external-helpers.js | 10 +- src/babel/transformation/file.js | 4 +- ...-binary-assignment-operator-transformer.js | 2 +- .../helpers/build-comprehension.js | 2 +- ...itional-assignment-operator-transformer.js | 2 +- .../helpers/build-react-transformer.js | 2 +- .../transformation/helpers/define-map.js | 2 +- .../helpers/explode-assignable-expression.js | 2 +- .../helpers/get-function-arity.js | 2 +- .../transformation/helpers/name-method.js | 2 +- src/babel/transformation/helpers/react.js | 2 +- src/babel/transformation/helpers/regex.js | 2 +- .../helpers/remap-async-to-generator.js | 2 +- .../transformation/helpers/replace-supers.js | 2 +- src/babel/transformation/helpers/strict.js | 2 +- src/babel/transformation/modules/_default.js | 2 +- src/babel/transformation/modules/amd.js | 2 +- src/babel/transformation/modules/common.js | 2 +- src/babel/transformation/modules/ignore.js | 2 +- src/babel/transformation/modules/system.js | 2 +- src/babel/transformation/modules/umd.js | 2 +- .../es3/member-expression-literals.js | 2 +- .../transformers/es3/property-literals.js | 2 +- .../transformers/es5/properties.mutators.js | 2 +- .../transformers/es6/arrow-functions.js | 2 +- .../transformers/es6/block-scoping-tdz.js | 2 +- .../transformers/es6/block-scoping.js | 2 +- .../transformers/es6/classes.js | 2 +- .../transformers/es6/constants.js | 2 +- .../transformers/es6/destructuring.js | 2 +- .../transformation/transformers/es6/for-of.js | 2 +- .../transformers/es6/modules.js | 2 +- .../transformers/es6/object-super.js | 2 +- .../transformers/es6/parameters.default.js | 2 +- .../transformers/es6/parameters.rest.js | 2 +- .../transformers/es6/properties.computed.js | 2 +- .../transformers/es6/properties.shorthand.js | 2 +- .../transformers/es6/regex.sticky.js | 2 +- .../transformation/transformers/es6/spread.js | 2 +- .../transformers/es6/symbols.js | 2 +- .../transformers/es6/tail-call.js | 2 +- .../transformers/es6/template-literals.js | 2 +- .../transformers/es7/abstract-references.js | 2 +- .../transformers/es7/comprehensions.js | 2 +- .../es7/exponentiation-operator.js | 2 +- .../transformers/es7/object-rest-spread.js | 2 +- .../transformers/internal/alias-functions.js | 2 +- .../transformers/internal/declarations.js | 2 +- .../transformers/internal/modules.js | 2 +- .../transformers/internal/strict.js | 2 +- .../transformers/internal/validation.js | 2 +- .../transformers/other/bluebird-coroutines.js | 2 +- .../transformation/transformers/other/flow.js | 2 +- .../transformers/other/react-compat.js | 2 +- .../transformers/other/react.js | 2 +- .../transformers/other/regenerator.js | 2 +- .../transformers/other/runtime.js | 2 +- .../transformers/other/strict.js | 2 +- .../playground/mallet-operator.js | 2 +- .../playground/memoization-operator.js | 2 +- .../transformers/playground/method-binding.js | 2 +- .../playground/object-getter-memoization.js | 2 +- .../spec/block-scoped-functions.js | 2 +- .../transformers/spec/proto-to-assign.js | 2 +- .../transformers/spec/undefined-to-void.js | 2 +- .../utility/dead-code-elimination.js | 2 +- .../utility/inline-environment-variables.js | 2 +- .../utility/inline-expressions.js | 2 +- .../transformers/utility/remove-console.js | 2 +- .../transformers/utility/remove-debugger.js | 2 +- .../transformers/validation/react.js | 2 +- src/babel/traversal/context.js | 2 +- src/babel/traversal/index.js | 2 +- src/babel/traversal/path.js | 10 +- src/babel/traversal/scope.js | 2 +- src/babel/types/converters.js | 230 ++++++ src/babel/types/evaluators.js | 129 +++ src/babel/types/index.js | 742 +----------------- src/babel/types/retrievers.js | 105 +++ src/babel/types/validators.js | 202 +++++ src/babel/util.js | 2 +- .../es6-classes/computed-methods/actual.js | 1 + .../es6-classes/computed-methods/expected.js | 3 + 96 files changed, 813 insertions(+), 795 deletions(-) create mode 100644 src/babel/types/converters.js create mode 100644 src/babel/types/evaluators.js create mode 100644 src/babel/types/retrievers.js create mode 100644 src/babel/types/validators.js diff --git a/src/babel/generation/generators/expressions.js b/src/babel/generation/generators/expressions.js index 650d3d9b68..5cfb36e62b 100644 --- a/src/babel/generation/generators/expressions.js +++ b/src/babel/generation/generators/expressions.js @@ -1,6 +1,6 @@ import isInteger from "is-integer"; import isNumber from "lodash/lang/isNumber"; -import t from "../../types"; +import * as t from "../../types"; export function UnaryExpression(node, print) { var hasSpace = /[a-z]$/.test(node.operator); diff --git a/src/babel/generation/generators/flow.js b/src/babel/generation/generators/flow.js index 661fd1c740..7ae499c22a 100644 --- a/src/babel/generation/generators/flow.js +++ b/src/babel/generation/generators/flow.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; export function AnyTypeAnnotation() { this.push("any"); diff --git a/src/babel/generation/generators/jsx.js b/src/babel/generation/generators/jsx.js index a467a627bf..83a5d6500e 100644 --- a/src/babel/generation/generators/jsx.js +++ b/src/babel/generation/generators/jsx.js @@ -1,5 +1,5 @@ import each from "lodash/collection/each"; -import t from "../../types"; +import * as t from "../../types"; export function JSXAttribute(node, print) { print(node.name); diff --git a/src/babel/generation/generators/methods.js b/src/babel/generation/generators/methods.js index d20bcf7add..7336a4ee86 100644 --- a/src/babel/generation/generators/methods.js +++ b/src/babel/generation/generators/methods.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; export function _params(node, print) { print(node.typeParameters); diff --git a/src/babel/generation/generators/modules.js b/src/babel/generation/generators/modules.js index b1299335d0..b7241adb3a 100644 --- a/src/babel/generation/generators/modules.js +++ b/src/babel/generation/generators/modules.js @@ -1,5 +1,5 @@ import each from "lodash/collection/each"; -import t from "../../types"; +import * as t from "../../types"; export function ImportSpecifier(node, print) { if (t.isSpecifierDefault(node)) { diff --git a/src/babel/generation/generators/statements.js b/src/babel/generation/generators/statements.js index 86edb6005e..c314d5360a 100644 --- a/src/babel/generation/generators/statements.js +++ b/src/babel/generation/generators/statements.js @@ -1,5 +1,5 @@ import repeating from "repeating"; -import t from "../../types"; +import * as t from "../../types"; export function WithStatement(node, print) { this.keyword("with"); diff --git a/src/babel/generation/index.js b/src/babel/generation/index.js index 6c0394d8e8..9a8baf610a 100644 --- a/src/babel/generation/index.js +++ b/src/babel/generation/index.js @@ -8,7 +8,7 @@ import Buffer from "./buffer"; import extend from "lodash/object/extend"; import each from "lodash/collection/each"; import n from "./node"; -import t from "../types"; +import * as t from "../types"; class CodeGenerator { constructor(ast, opts, code) { diff --git a/src/babel/generation/node/index.js b/src/babel/generation/node/index.js index c1b0fdf2ed..8b655bb9b3 100644 --- a/src/babel/generation/node/index.js +++ b/src/babel/generation/node/index.js @@ -2,7 +2,7 @@ import whitespace from "./whitespace"; import * as parens from "./parentheses"; import each from "lodash/collection/each"; import some from "lodash/collection/some"; -import t from "../../types"; +import * as t from "../../types"; var find = function (obj, node, parent) { if (!obj) return; diff --git a/src/babel/generation/node/parentheses.js b/src/babel/generation/node/parentheses.js index 3645a2b089..e429dca474 100644 --- a/src/babel/generation/node/parentheses.js +++ b/src/babel/generation/node/parentheses.js @@ -1,5 +1,5 @@ import each from "lodash/collection/each"; -import t from "../../types"; +import * as t from "../../types"; var PRECEDENCE = {}; diff --git a/src/babel/generation/node/whitespace.js b/src/babel/generation/node/whitespace.js index c4ae5e0bba..1db5d42d42 100644 --- a/src/babel/generation/node/whitespace.js +++ b/src/babel/generation/node/whitespace.js @@ -1,7 +1,7 @@ import isBoolean from "lodash/lang/isBoolean"; import each from "lodash/collection/each"; import map from "lodash/collection/map"; -import t from "../../types"; +import * as t from "../../types"; function crawl(node, state = {}) { if (t.isMemberExpression(node)) { diff --git a/src/babel/generation/source-map.js b/src/babel/generation/source-map.js index 5761ef39ba..1ce084a365 100644 --- a/src/babel/generation/source-map.js +++ b/src/babel/generation/source-map.js @@ -1,5 +1,5 @@ import sourceMap from "source-map"; -import t from "../types"; +import * as t from "../types"; export default class SourceMap { constructor(position, opts, code) { diff --git a/src/babel/helpers/normalize-ast.js b/src/babel/helpers/normalize-ast.js index d7fea96cd2..f02c4182ce 100644 --- a/src/babel/helpers/normalize-ast.js +++ b/src/babel/helpers/normalize-ast.js @@ -1,4 +1,4 @@ -import t from "../types"; +import * as t from "../types"; export default function (ast, comments, tokens) { if (ast && ast.type === "Program") { diff --git a/src/babel/patch.js b/src/babel/patch.js index bac1c1c4bd..46078aa9d6 100644 --- a/src/babel/patch.js +++ b/src/babel/patch.js @@ -1,7 +1,7 @@ import estraverse from "estraverse"; import extend from "lodash/object/extend"; import types from "ast-types"; -import t from "./types"; +import * as t from "./types"; // estraverse diff --git a/src/babel/tools/build-external-helpers.js b/src/babel/tools/build-external-helpers.js index 91c393fcc5..e2e03c88a2 100644 --- a/src/babel/tools/build-external-helpers.js +++ b/src/babel/tools/build-external-helpers.js @@ -1,9 +1,9 @@ -import generator from "./generation"; -import * as messages from "./messages"; -import * as util from "./util"; -import File from "./transformation/file"; +import generator from "../generation"; +import * as messages from "../messages"; +import * as util from "../util"; +import File from "../transformation/file"; import each from "lodash/collection/each"; -import t from "./types"; +import * as t from "../types"; function buildGlobal(namespace, builder) { var body = []; diff --git a/src/babel/transformation/file.js b/src/babel/transformation/file.js index 840fb357bd..900ffc3106 100644 --- a/src/babel/transformation/file.js +++ b/src/babel/transformation/file.js @@ -14,7 +14,7 @@ import slash from "slash"; import * as util from "../util"; import path from "path"; import each from "lodash/collection/each"; -import t from "../types"; +import * as t from "../types"; var checkTransformerVisitor = { enter(node, parent, scope, state) { @@ -423,7 +423,7 @@ export default class File { } transform(ast) { - this.debug(); + this.log.debug(); this.ast = ast; this.lastStatements = t.getLastStatements(ast.program); diff --git a/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js b/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js index e575daa9fd..87511d54ab 100644 --- a/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js +++ b/src/babel/transformation/helpers/build-binary-assignment-operator-transformer.js @@ -1,5 +1,5 @@ import explode from "./explode-assignable-expression"; -import t from "../../types"; +import * as t from "../../types"; export default function (exports, opts) { var isAssignment = function (node) { diff --git a/src/babel/transformation/helpers/build-comprehension.js b/src/babel/transformation/helpers/build-comprehension.js index 795fa19d63..c19bbf8c18 100644 --- a/src/babel/transformation/helpers/build-comprehension.js +++ b/src/babel/transformation/helpers/build-comprehension.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; export default function build(node, buildBody) { var self = node.blocks.shift(); diff --git a/src/babel/transformation/helpers/build-conditional-assignment-operator-transformer.js b/src/babel/transformation/helpers/build-conditional-assignment-operator-transformer.js index 4c30b38bc5..d245e13b89 100644 --- a/src/babel/transformation/helpers/build-conditional-assignment-operator-transformer.js +++ b/src/babel/transformation/helpers/build-conditional-assignment-operator-transformer.js @@ -1,5 +1,5 @@ import explode from "./explode-assignable-expression"; -import t from "../../types"; +import * as t from "../../types"; export default function (exports, opts) { var buildAssignment = function (left, right) { diff --git a/src/babel/transformation/helpers/build-react-transformer.js b/src/babel/transformation/helpers/build-react-transformer.js index 5fe2f27942..02b9ba1ffe 100644 --- a/src/babel/transformation/helpers/build-react-transformer.js +++ b/src/babel/transformation/helpers/build-react-transformer.js @@ -7,7 +7,7 @@ import isString from "lodash/lang/isString"; import * as messages from "../../messages"; import esutils from "esutils"; import * as react from "./react"; -import t from "../../types"; +import * as t from "../../types"; export default function (exports, opts) { exports.check = function (node) { diff --git a/src/babel/transformation/helpers/define-map.js b/src/babel/transformation/helpers/define-map.js index 068cb899bc..4dcf58d87a 100644 --- a/src/babel/transformation/helpers/define-map.js +++ b/src/babel/transformation/helpers/define-map.js @@ -2,7 +2,7 @@ import cloneDeep from "lodash/lang/cloneDeep"; import traverse from "../../traversal"; import each from "lodash/collection/each"; import has from "lodash/object/has"; -import t from "../../types"; +import * as t from "../../types"; export function push(mutatorMap, key, kind, computed, value) { var alias = t.toKeyAlias({ computed }, key); diff --git a/src/babel/transformation/helpers/explode-assignable-expression.js b/src/babel/transformation/helpers/explode-assignable-expression.js index 29daf31f3c..4c0ed87664 100644 --- a/src/babel/transformation/helpers/explode-assignable-expression.js +++ b/src/babel/transformation/helpers/explode-assignable-expression.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; var getObjRef = function (node, nodes, file, scope) { var ref; diff --git a/src/babel/transformation/helpers/get-function-arity.js b/src/babel/transformation/helpers/get-function-arity.js index 5f2d94b61f..da78d174c7 100644 --- a/src/babel/transformation/helpers/get-function-arity.js +++ b/src/babel/transformation/helpers/get-function-arity.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; export default function (node) { var lastNonDefault = 0; diff --git a/src/babel/transformation/helpers/name-method.js b/src/babel/transformation/helpers/name-method.js index 3de58f067e..406ca92bc6 100644 --- a/src/babel/transformation/helpers/name-method.js +++ b/src/babel/transformation/helpers/name-method.js @@ -1,6 +1,6 @@ import getFunctionArity from "./get-function-arity"; import * as util from "../../util"; -import t from "../../types"; +import * as t from "../../types"; var visitor = { enter(node, parent, scope, state) { diff --git a/src/babel/transformation/helpers/react.js b/src/babel/transformation/helpers/react.js index a5f1f6fdf5..25ea7f9dba 100644 --- a/src/babel/transformation/helpers/react.js +++ b/src/babel/transformation/helpers/react.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; var isCreateClassCallExpression = t.buildMatchMemberExpression("React.createClass"); diff --git a/src/babel/transformation/helpers/regex.js b/src/babel/transformation/helpers/regex.js index 1624d7a8ec..9251fdb823 100644 --- a/src/babel/transformation/helpers/regex.js +++ b/src/babel/transformation/helpers/regex.js @@ -1,5 +1,5 @@ import pull from "lodash/array/pull"; -import t from "../../types"; +import * as t from "../../types"; export function is(node, flag) { return t.isLiteral(node) && node.regex && node.regex.flags.indexOf(flag) >= 0; diff --git a/src/babel/transformation/helpers/remap-async-to-generator.js b/src/babel/transformation/helpers/remap-async-to-generator.js index 868d16a624..56faaeb7ab 100644 --- a/src/babel/transformation/helpers/remap-async-to-generator.js +++ b/src/babel/transformation/helpers/remap-async-to-generator.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; var awaitVisitor = { enter(node, parent, scope, state) { diff --git a/src/babel/transformation/helpers/replace-supers.js b/src/babel/transformation/helpers/replace-supers.js index d0a529be40..e60cbabcb4 100644 --- a/src/babel/transformation/helpers/replace-supers.js +++ b/src/babel/transformation/helpers/replace-supers.js @@ -1,7 +1,7 @@ module.exports = ReplaceSupers; import * as messages from "../../messages"; -import t from "../../types"; +import * as t from "../../types"; function isIllegalBareSuper(node, parent) { diff --git a/src/babel/transformation/helpers/strict.js b/src/babel/transformation/helpers/strict.js index d5dbe31b41..737c9a6f26 100644 --- a/src/babel/transformation/helpers/strict.js +++ b/src/babel/transformation/helpers/strict.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; export function has(node) { var first = node.body[0]; diff --git a/src/babel/transformation/modules/_default.js b/src/babel/transformation/modules/_default.js index 838162b6a5..a60d3b7507 100644 --- a/src/babel/transformation/modules/_default.js +++ b/src/babel/transformation/modules/_default.js @@ -2,7 +2,7 @@ import * as messages from "../../messages"; import extend from "lodash/object/extend"; import object from "../../helpers/object"; import * as util from "../../util"; -import t from "../../types"; +import * as t from "../../types"; var remapVisitor = { enter(node, parent, scope, formatter) { diff --git a/src/babel/transformation/modules/amd.js b/src/babel/transformation/modules/amd.js index b7a93736d1..ce347bdb05 100644 --- a/src/babel/transformation/modules/amd.js +++ b/src/babel/transformation/modules/amd.js @@ -3,7 +3,7 @@ import CommonFormatter from "./common"; import includes from "lodash/collection/includes"; import values from "lodash/object/values"; import * as util from "../../util"; -import t from "../../types"; +import * as t from "../../types"; export default class AMDFormatter extends DefaultFormatter { init = CommonFormatter.prototype.init; diff --git a/src/babel/transformation/modules/common.js b/src/babel/transformation/modules/common.js index 418ecf6dd6..6cd4509bb6 100644 --- a/src/babel/transformation/modules/common.js +++ b/src/babel/transformation/modules/common.js @@ -1,7 +1,7 @@ import DefaultFormatter from "./_default"; import includes from "lodash/collection/includes"; import * as util from "../../util"; -import t from "../../types"; +import * as t from "../../types"; export default class CommonJSFormatter extends DefaultFormatter { init() { diff --git a/src/babel/transformation/modules/ignore.js b/src/babel/transformation/modules/ignore.js index 5050f89d16..fcee260908 100644 --- a/src/babel/transformation/modules/ignore.js +++ b/src/babel/transformation/modules/ignore.js @@ -1,4 +1,4 @@ -import t from "../../types"; +import * as t from "../../types"; export default class IgnoreFormatter { exportDeclaration(node, nodes) { diff --git a/src/babel/transformation/modules/system.js b/src/babel/transformation/modules/system.js index 6274d98b67..2471159594 100644 --- a/src/babel/transformation/modules/system.js +++ b/src/babel/transformation/modules/system.js @@ -4,7 +4,7 @@ import * as util from "../../util"; import last from "lodash/array/last"; import each from "lodash/collection/each"; import map from "lodash/collection/map"; -import t from "../../types"; +import * as t from "../../types"; var hoistVariablesVisitor = { enter(node, parent, scope, hoistDeclarators) { diff --git a/src/babel/transformation/modules/umd.js b/src/babel/transformation/modules/umd.js index d130318b22..d932dece37 100644 --- a/src/babel/transformation/modules/umd.js +++ b/src/babel/transformation/modules/umd.js @@ -1,7 +1,7 @@ import AMDFormatter from "./amd"; import values from "lodash/object/values"; import * as util from "../../util"; -import t from "../../types"; +import * as t from "../../types"; export default class UMDFormatter extends AMDFormatter { transform(program) { diff --git a/src/babel/transformation/transformers/es3/member-expression-literals.js b/src/babel/transformation/transformers/es3/member-expression-literals.js index 5199bc82be..be8c207560 100644 --- a/src/babel/transformation/transformers/es3/member-expression-literals.js +++ b/src/babel/transformation/transformers/es3/member-expression-literals.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export function MemberExpression(node) { var prop = node.property; diff --git a/src/babel/transformation/transformers/es3/property-literals.js b/src/babel/transformation/transformers/es3/property-literals.js index 1e61ce2f3a..407b33df78 100644 --- a/src/babel/transformation/transformers/es3/property-literals.js +++ b/src/babel/transformation/transformers/es3/property-literals.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export function Property(node) { var key = node.key; diff --git a/src/babel/transformation/transformers/es5/properties.mutators.js b/src/babel/transformation/transformers/es5/properties.mutators.js index d8feebc088..e2cd098722 100644 --- a/src/babel/transformation/transformers/es5/properties.mutators.js +++ b/src/babel/transformation/transformers/es5/properties.mutators.js @@ -1,5 +1,5 @@ import * as defineMap from "../../helpers/define-map"; -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return t.isProperty(node) && (node.kind === "get" || node.kind === "set"); diff --git a/src/babel/transformation/transformers/es6/arrow-functions.js b/src/babel/transformation/transformers/es6/arrow-functions.js index e5cfd1db48..9751ee25f3 100644 --- a/src/babel/transformation/transformers/es6/arrow-functions.js +++ b/src/babel/transformation/transformers/es6/arrow-functions.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var check = t.isArrowFunctionExpression; diff --git a/src/babel/transformation/transformers/es6/block-scoping-tdz.js b/src/babel/transformation/transformers/es6/block-scoping-tdz.js index e90374ee3a..d18333a192 100644 --- a/src/babel/transformation/transformers/es6/block-scoping-tdz.js +++ b/src/babel/transformation/transformers/es6/block-scoping-tdz.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; var visitor = { enter(node, parent, scope, state) { diff --git a/src/babel/transformation/transformers/es6/block-scoping.js b/src/babel/transformation/transformers/es6/block-scoping.js index 2c6e531d1f..998f870215 100644 --- a/src/babel/transformation/transformers/es6/block-scoping.js +++ b/src/babel/transformation/transformers/es6/block-scoping.js @@ -1,7 +1,7 @@ import traverse from "../../../traversal"; import object from "../../../helpers/object"; import * as util from "../../../util"; -import t from "../../../types"; +import * as t from "../../../types"; import values from "lodash/object/values"; import extend from "lodash/object/extend"; diff --git a/src/babel/transformation/transformers/es6/classes.js b/src/babel/transformation/transformers/es6/classes.js index dd62afe344..f0ccc38c5f 100644 --- a/src/babel/transformation/transformers/es6/classes.js +++ b/src/babel/transformation/transformers/es6/classes.js @@ -4,7 +4,7 @@ import * as defineMap from "../../helpers/define-map"; import * as messages from "../../../messages"; import * as util from "../../../util"; import traverse from "../../../traversal"; -import t from "../../../types"; +import * as t from "../../../types"; export var check = t.isClass; diff --git a/src/babel/transformation/transformers/es6/constants.js b/src/babel/transformation/transformers/es6/constants.js index 519d565f42..fc29e8c916 100644 --- a/src/babel/transformation/transformers/es6/constants.js +++ b/src/babel/transformation/transformers/es6/constants.js @@ -1,5 +1,5 @@ import * as messages from "../../../messages"; -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return t.isVariableDeclaration(node, { kind: "const" }); diff --git a/src/babel/transformation/transformers/es6/destructuring.js b/src/babel/transformation/transformers/es6/destructuring.js index 9651bb2b54..ea9e3bdaf3 100644 --- a/src/babel/transformation/transformers/es6/destructuring.js +++ b/src/babel/transformation/transformers/es6/destructuring.js @@ -1,5 +1,5 @@ import * as messages from "../../../messages"; -import t from "../../../types"; +import * as t from "../../../types"; export var check = t.isPattern; diff --git a/src/babel/transformation/transformers/es6/for-of.js b/src/babel/transformation/transformers/es6/for-of.js index 2113c41044..28f7d98df0 100644 --- a/src/babel/transformation/transformers/es6/for-of.js +++ b/src/babel/transformation/transformers/es6/for-of.js @@ -1,6 +1,6 @@ import * as messages from "../../../messages"; import * as util from "../../../util"; -import t from "../../../types"; +import * as t from "../../../types"; export var check = t.isForOfStatement; diff --git a/src/babel/transformation/transformers/es6/modules.js b/src/babel/transformation/transformers/es6/modules.js index 41ff9f729b..0eab992dfe 100644 --- a/src/babel/transformation/transformers/es6/modules.js +++ b/src/babel/transformation/transformers/es6/modules.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export { check } from "../internal/modules"; diff --git a/src/babel/transformation/transformers/es6/object-super.js b/src/babel/transformation/transformers/es6/object-super.js index cf23f6bba0..dd4dbf4d8e 100644 --- a/src/babel/transformation/transformers/es6/object-super.js +++ b/src/babel/transformation/transformers/es6/object-super.js @@ -1,5 +1,5 @@ import ReplaceSupers from "../../helpers/replace-supers"; -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return t.isIdentifier(node, { name: "super" }); diff --git a/src/babel/transformation/transformers/es6/parameters.default.js b/src/babel/transformation/transformers/es6/parameters.default.js index 1a5ae2af76..9e525c87d3 100644 --- a/src/babel/transformation/transformers/es6/parameters.default.js +++ b/src/babel/transformation/transformers/es6/parameters.default.js @@ -1,5 +1,5 @@ import * as util from "../../../util"; -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return t.isFunction(node) && hasDefaults(node); diff --git a/src/babel/transformation/transformers/es6/parameters.rest.js b/src/babel/transformation/transformers/es6/parameters.rest.js index feec0fdc74..14098fa0e3 100644 --- a/src/babel/transformation/transformers/es6/parameters.rest.js +++ b/src/babel/transformation/transformers/es6/parameters.rest.js @@ -1,6 +1,6 @@ import isNumber from "lodash/lang/isNumber"; import * as util from "../../../util"; -import t from "../../../types"; +import * as t from "../../../types"; export var check = t.isRestElement; diff --git a/src/babel/transformation/transformers/es6/properties.computed.js b/src/babel/transformation/transformers/es6/properties.computed.js index 1788a1ee85..ca1f9ee715 100644 --- a/src/babel/transformation/transformers/es6/properties.computed.js +++ b/src/babel/transformation/transformers/es6/properties.computed.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; function loose(node, body, objId) { for (var i = 0; i < node.properties.length; i++) { diff --git a/src/babel/transformation/transformers/es6/properties.shorthand.js b/src/babel/transformation/transformers/es6/properties.shorthand.js index 42e11302e2..c3a4aeb776 100644 --- a/src/babel/transformation/transformers/es6/properties.shorthand.js +++ b/src/babel/transformation/transformers/es6/properties.shorthand.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return t.isProperty(node) && (node.method || node.shorthand); diff --git a/src/babel/transformation/transformers/es6/regex.sticky.js b/src/babel/transformation/transformers/es6/regex.sticky.js index 0281df3308..988ab2d8aa 100644 --- a/src/babel/transformation/transformers/es6/regex.sticky.js +++ b/src/babel/transformation/transformers/es6/regex.sticky.js @@ -1,5 +1,5 @@ import * as regex from "../../helpers/regex"; -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return regex.is(node, "y"); diff --git a/src/babel/transformation/transformers/es6/spread.js b/src/babel/transformation/transformers/es6/spread.js index f83f2de3a6..4fe2b7d238 100644 --- a/src/babel/transformation/transformers/es6/spread.js +++ b/src/babel/transformation/transformers/es6/spread.js @@ -1,5 +1,5 @@ import includes from "lodash/collection/includes"; -import t from "../../../types"; +import * as t from "../../../types"; function getSpreadLiteral(spread, scope) { return scope.toArray(spread.argument, true); diff --git a/src/babel/transformation/transformers/es6/symbols.js b/src/babel/transformation/transformers/es6/symbols.js index 5f4ddab5e4..fd3fe51b7e 100644 --- a/src/babel/transformation/transformers/es6/symbols.js +++ b/src/babel/transformation/transformers/es6/symbols.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var optional = true; diff --git a/src/babel/transformation/transformers/es6/tail-call.js b/src/babel/transformation/transformers/es6/tail-call.js index 6d55c1adf8..e7439cdf5a 100644 --- a/src/babel/transformation/transformers/es6/tail-call.js +++ b/src/babel/transformation/transformers/es6/tail-call.js @@ -3,7 +3,7 @@ import * as messages from "../../../messages"; import flatten from "lodash/array/flatten"; import * as util from "../../../util"; import map from "lodash/collection/map"; -import t from "../../../types"; +import * as t from "../../../types"; exports.Function = function (node, parent, scope, file) { var tailCall = new TailCallTransformer(node, scope, file); diff --git a/src/babel/transformation/transformers/es6/template-literals.js b/src/babel/transformation/transformers/es6/template-literals.js index c2ebf2e788..9bee577561 100644 --- a/src/babel/transformation/transformers/es6/template-literals.js +++ b/src/babel/transformation/transformers/es6/template-literals.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; var buildBinaryExpression = function (left, right) { return t.binaryExpression("+", left, right); diff --git a/src/babel/transformation/transformers/es7/abstract-references.js b/src/babel/transformation/transformers/es7/abstract-references.js index 4443428fc2..7713b41444 100644 --- a/src/babel/transformation/transformers/es7/abstract-references.js +++ b/src/babel/transformation/transformers/es7/abstract-references.js @@ -1,7 +1,7 @@ // https://github.com/zenparsing/es-abstract-refs import * as util from "../../../util"; -import t from "../../../types"; +import * as t from "../../../types"; export var experimental = true; diff --git a/src/babel/transformation/transformers/es7/comprehensions.js b/src/babel/transformation/transformers/es7/comprehensions.js index 6ff0ba400e..98484701b0 100644 --- a/src/babel/transformation/transformers/es7/comprehensions.js +++ b/src/babel/transformation/transformers/es7/comprehensions.js @@ -1,7 +1,7 @@ import buildComprehension from "../../helpers/build-comprehension"; import traverse from "../../../traversal"; import * as util from "../../../util"; -import t from "../../../types"; +import * as t from "../../../types"; export var experimental = true; diff --git a/src/babel/transformation/transformers/es7/exponentiation-operator.js b/src/babel/transformation/transformers/es7/exponentiation-operator.js index cc5d1c93f7..da988d07dd 100644 --- a/src/babel/transformation/transformers/es7/exponentiation-operator.js +++ b/src/babel/transformation/transformers/es7/exponentiation-operator.js @@ -1,7 +1,7 @@ // https://github.com/rwaldron/exponentiation-operator import build from "../../helpers/build-binary-assignment-operator-transformer"; -import t from "../../../types"; +import * as t from "../../../types"; export var experimental = true; diff --git a/src/babel/transformation/transformers/es7/object-rest-spread.js b/src/babel/transformation/transformers/es7/object-rest-spread.js index b555e9b62f..c5d7b08c3d 100644 --- a/src/babel/transformation/transformers/es7/object-rest-spread.js +++ b/src/babel/transformation/transformers/es7/object-rest-spread.js @@ -1,6 +1,6 @@ // https://github.com/sebmarkbage/ecmascript-rest-spread -import t from "../../../types"; +import * as t from "../../../types"; export var experimental = true; diff --git a/src/babel/transformation/transformers/internal/alias-functions.js b/src/babel/transformation/transformers/internal/alias-functions.js index 22b4a511ee..b76e19ae50 100644 --- a/src/babel/transformation/transformers/internal/alias-functions.js +++ b/src/babel/transformation/transformers/internal/alias-functions.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; var functionChildrenVisitor = { enter(node, parent, scope, state) { diff --git a/src/babel/transformation/transformers/internal/declarations.js b/src/babel/transformation/transformers/internal/declarations.js index 81ed9c939c..01dd233eab 100644 --- a/src/babel/transformation/transformers/internal/declarations.js +++ b/src/babel/transformation/transformers/internal/declarations.js @@ -1,5 +1,5 @@ import * as strict from "../../helpers/strict"; -import t from "../../../types"; +import * as t from "../../../types"; export var secondPass = true; diff --git a/src/babel/transformation/transformers/internal/modules.js b/src/babel/transformation/transformers/internal/modules.js index 4e63035e78..7ef5bc5302 100644 --- a/src/babel/transformation/transformers/internal/modules.js +++ b/src/babel/transformation/transformers/internal/modules.js @@ -4,7 +4,7 @@ // a generator function as a default then regenerator will destroy the export // declaration and leave a variable declaration in it's place... yeah, handy. -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return t.isImportDeclaration(node) || t.isExportDeclaration(node); diff --git a/src/babel/transformation/transformers/internal/strict.js b/src/babel/transformation/transformers/internal/strict.js index c4e0bfa695..84a1ee0499 100644 --- a/src/babel/transformation/transformers/internal/strict.js +++ b/src/babel/transformation/transformers/internal/strict.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export function Program(program, parent, scope, file) { if (file.transformers.strict.canRun()) { diff --git a/src/babel/transformation/transformers/internal/validation.js b/src/babel/transformation/transformers/internal/validation.js index 49b39429b3..600c2aa3d5 100644 --- a/src/babel/transformation/transformers/internal/validation.js +++ b/src/babel/transformation/transformers/internal/validation.js @@ -1,5 +1,5 @@ import * as messages from "../../../messages"; -import t from "../../../types"; +import * as t from "../../../types"; export function ForOfStatement(node, parent, scope, file) { var left = node.left; diff --git a/src/babel/transformation/transformers/other/bluebird-coroutines.js b/src/babel/transformation/transformers/other/bluebird-coroutines.js index b03fc88477..67a8a474c0 100644 --- a/src/babel/transformation/transformers/other/bluebird-coroutines.js +++ b/src/babel/transformation/transformers/other/bluebird-coroutines.js @@ -1,5 +1,5 @@ import remapAsyncToGenerator from "../../helpers/remap-async-to-generator"; -import t from "../../../types"; +import * as t from "../../../types"; export function manipulateOptions(opts) { opts.experimental = true; diff --git a/src/babel/transformation/transformers/other/flow.js b/src/babel/transformation/transformers/other/flow.js index 01ceb3f990..4f8126f9f9 100644 --- a/src/babel/transformation/transformers/other/flow.js +++ b/src/babel/transformation/transformers/other/flow.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export function Flow(node) { this.remove(); diff --git a/src/babel/transformation/transformers/other/react-compat.js b/src/babel/transformation/transformers/other/react-compat.js index 2e20d02266..49e37338f1 100644 --- a/src/babel/transformation/transformers/other/react-compat.js +++ b/src/babel/transformation/transformers/other/react-compat.js @@ -1,5 +1,5 @@ import * as react from "../../helpers/react"; -import t from "../../../types"; +import * as t from "../../../types"; export function manipulateOptions(opts) { opts.blacklist.push("react"); diff --git a/src/babel/transformation/transformers/other/react.js b/src/babel/transformation/transformers/other/react.js index b74e3f3436..2b098e5461 100644 --- a/src/babel/transformation/transformers/other/react.js +++ b/src/babel/transformation/transformers/other/react.js @@ -1,5 +1,5 @@ import * as react from "../../helpers/react"; -import t from "../../../types"; +import * as t from "../../../types"; var JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/; diff --git a/src/babel/transformation/transformers/other/regenerator.js b/src/babel/transformation/transformers/other/regenerator.js index 492f81a6c5..24df02bac3 100644 --- a/src/babel/transformation/transformers/other/regenerator.js +++ b/src/babel/transformation/transformers/other/regenerator.js @@ -1,5 +1,5 @@ import regenerator from "regenerator-babel"; -import t from "../../../types"; +import * as t from "../../../types"; export function check(node) { return t.isFunction(node) && (node.async || node.generator); diff --git a/src/babel/transformation/transformers/other/runtime.js b/src/babel/transformation/transformers/other/runtime.js index 6b3fd00e45..a137603e8c 100644 --- a/src/babel/transformation/transformers/other/runtime.js +++ b/src/babel/transformation/transformers/other/runtime.js @@ -2,7 +2,7 @@ import includes from "lodash/collection/includes"; import * as util from "../../../util"; import core from "core-js/library"; import has from "lodash/object/has"; -import t from "../../../types"; +import * as t from "../../../types"; var isSymboliterator = t.buildMatchMemberExpression("Symbol.iterator"); diff --git a/src/babel/transformation/transformers/other/strict.js b/src/babel/transformation/transformers/other/strict.js index aa2a856f24..db7849059a 100644 --- a/src/babel/transformation/transformers/other/strict.js +++ b/src/babel/transformation/transformers/other/strict.js @@ -1,5 +1,5 @@ import * as messages from "../../../messages"; -import t from "../../../types"; +import * as t from "../../../types"; export function Program(program) { var first = program.body[0]; diff --git a/src/babel/transformation/transformers/playground/mallet-operator.js b/src/babel/transformation/transformers/playground/mallet-operator.js index c70a13d62b..25e6896a45 100644 --- a/src/babel/transformation/transformers/playground/mallet-operator.js +++ b/src/babel/transformation/transformers/playground/mallet-operator.js @@ -1,6 +1,6 @@ import * as messages from "../../../messages"; import build from "../../helpers/build-conditional-assignment-operator-transformer"; -import t from "../../../types"; +import * as t from "../../../types"; export var playground = true; diff --git a/src/babel/transformation/transformers/playground/memoization-operator.js b/src/babel/transformation/transformers/playground/memoization-operator.js index 1939472db6..7c63ad102a 100644 --- a/src/babel/transformation/transformers/playground/memoization-operator.js +++ b/src/babel/transformation/transformers/playground/memoization-operator.js @@ -1,5 +1,5 @@ import build from "../../helpers/build-conditional-assignment-operator-transformer"; -import t from "../../../types"; +import * as t from "../../../types"; export var playground = true; diff --git a/src/babel/transformation/transformers/playground/method-binding.js b/src/babel/transformation/transformers/playground/method-binding.js index 74d3fed196..5d4ddff3c7 100644 --- a/src/babel/transformation/transformers/playground/method-binding.js +++ b/src/babel/transformation/transformers/playground/method-binding.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var playground = true; diff --git a/src/babel/transformation/transformers/playground/object-getter-memoization.js b/src/babel/transformation/transformers/playground/object-getter-memoization.js index 14b63dc454..af5ffe8c4c 100644 --- a/src/babel/transformation/transformers/playground/object-getter-memoization.js +++ b/src/babel/transformation/transformers/playground/object-getter-memoization.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var playground = true; diff --git a/src/babel/transformation/transformers/spec/block-scoped-functions.js b/src/babel/transformation/transformers/spec/block-scoped-functions.js index 034339e12a..9240c25f28 100644 --- a/src/babel/transformation/transformers/spec/block-scoped-functions.js +++ b/src/babel/transformation/transformers/spec/block-scoped-functions.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export function BlockStatement(node, parent, scope, file) { if ((t.isFunction(parent) && parent.body === node) || t.isExportDeclaration(parent)) { diff --git a/src/babel/transformation/transformers/spec/proto-to-assign.js b/src/babel/transformation/transformers/spec/proto-to-assign.js index c3e4a1d7ad..188d21c03b 100644 --- a/src/babel/transformation/transformers/spec/proto-to-assign.js +++ b/src/babel/transformation/transformers/spec/proto-to-assign.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; import pull from "lodash/array/pull"; function isProtoKey(node) { diff --git a/src/babel/transformation/transformers/spec/undefined-to-void.js b/src/babel/transformation/transformers/spec/undefined-to-void.js index c3b284bdf3..ddd7af5317 100644 --- a/src/babel/transformation/transformers/spec/undefined-to-void.js +++ b/src/babel/transformation/transformers/spec/undefined-to-void.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var optional = true; diff --git a/src/babel/transformation/transformers/utility/dead-code-elimination.js b/src/babel/transformation/transformers/utility/dead-code-elimination.js index 486b31edee..3dd7252ae3 100644 --- a/src/babel/transformation/transformers/utility/dead-code-elimination.js +++ b/src/babel/transformation/transformers/utility/dead-code-elimination.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; function toStatements(node) { if (t.isBlockStatement(node)) { diff --git a/src/babel/transformation/transformers/utility/inline-environment-variables.js b/src/babel/transformation/transformers/utility/inline-environment-variables.js index cd03fc1718..5c62f53a6e 100644 --- a/src/babel/transformation/transformers/utility/inline-environment-variables.js +++ b/src/babel/transformation/transformers/utility/inline-environment-variables.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var optional = true; diff --git a/src/babel/transformation/transformers/utility/inline-expressions.js b/src/babel/transformation/transformers/utility/inline-expressions.js index b95ee1585c..9b77422502 100644 --- a/src/babel/transformation/transformers/utility/inline-expressions.js +++ b/src/babel/transformation/transformers/utility/inline-expressions.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var optional = true; diff --git a/src/babel/transformation/transformers/utility/remove-console.js b/src/babel/transformation/transformers/utility/remove-console.js index c5631ce8a2..791b17c9f4 100644 --- a/src/babel/transformation/transformers/utility/remove-console.js +++ b/src/babel/transformation/transformers/utility/remove-console.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; var isConsole = t.buildMatchMemberExpression("console", true); diff --git a/src/babel/transformation/transformers/utility/remove-debugger.js b/src/babel/transformation/transformers/utility/remove-debugger.js index 20a8583274..45d5727340 100644 --- a/src/babel/transformation/transformers/utility/remove-debugger.js +++ b/src/babel/transformation/transformers/utility/remove-debugger.js @@ -1,4 +1,4 @@ -import t from "../../../types"; +import * as t from "../../../types"; export var optional = true; diff --git a/src/babel/transformation/transformers/validation/react.js b/src/babel/transformation/transformers/validation/react.js index 3a04444b22..f8cbc58ffb 100644 --- a/src/babel/transformation/transformers/validation/react.js +++ b/src/babel/transformation/transformers/validation/react.js @@ -1,5 +1,5 @@ import * as messages from "../../../messages"; -import t from "../../../types"; +import * as t from "../../../types"; // check if the input Literal `source` is an alternate casing of "react" function check(source, file) { diff --git a/src/babel/traversal/context.js b/src/babel/traversal/context.js index 883017e559..f1031718c8 100644 --- a/src/babel/traversal/context.js +++ b/src/babel/traversal/context.js @@ -1,7 +1,7 @@ import TraversalPath from "./path"; import flatten from "lodash/array/flatten"; import compact from "lodash/array/compact"; -import t from "../types"; +import * as t from "../types"; export default class TraversalContext { constructor(scope, opts, state, parentPath) { diff --git a/src/babel/traversal/index.js b/src/babel/traversal/index.js index f815f53ff6..86c94d9fbe 100644 --- a/src/babel/traversal/index.js +++ b/src/babel/traversal/index.js @@ -2,7 +2,7 @@ module.exports = traverse; import TraversalContext from "./context"; import includes from "lodash/collection/includes"; -import t from "../types"; +import * as t from "../types"; function traverse(parent, opts, scope, state) { if (!parent) return; diff --git a/src/babel/traversal/path.js b/src/babel/traversal/path.js index 8456065d2b..fb5c204050 100644 --- a/src/babel/traversal/path.js +++ b/src/babel/traversal/path.js @@ -1,7 +1,7 @@ import traverse from "./index"; import includes from "lodash/collection/includes"; import Scope from "./scope"; -import t from "../types"; +import * as t from "../types"; export default class TraversalPath { constructor(parent, container) { @@ -44,6 +44,14 @@ export default class TraversalPath { return ourScope; } + insertBefore(node) { + + } + + insertAfter(node) { + + } + setData(key, val) { return this.data[key] = val; } diff --git a/src/babel/traversal/scope.js b/src/babel/traversal/scope.js index 453b758982..5c006703b8 100644 --- a/src/babel/traversal/scope.js +++ b/src/babel/traversal/scope.js @@ -7,7 +7,7 @@ import flatten from "lodash/array/flatten"; import extend from "lodash/object/extend"; import object from "../helpers/object"; import each from "lodash/collection/each"; -import t from "../types"; +import * as t from "../types"; var functionVariableVisitor = { enter(node, parent, scope, state) { diff --git a/src/babel/types/converters.js b/src/babel/types/converters.js new file mode 100644 index 0000000000..ea3a240ff3 --- /dev/null +++ b/src/babel/types/converters.js @@ -0,0 +1,230 @@ +import isPlainObject from "lodash/lang/isPlainObject"; +import isNumber from "lodash/lang/isNumber"; +import isRegExp from "lodash/lang/isRegExp"; +import isString from "lodash/lang/isString"; +import traverse from "../traversal"; +import each from "lodash/collection/each"; +import * as t from "./index"; + +/** + * Description + */ + +export function toComputedKey(node: Object, key: Object = node.key): Object { + if (!node.computed) { + if (t.isIdentifier(key)) key = t.literal(key.name); + } + return key; +} + +/** + * 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 { + var exprs = []; + + each(nodes, function (node) { + if (t.isExpression(node)) { + exprs.push(node); + } if (t.isExpressionStatement(node)) { + exprs.push(node.expression); + } else if (t.isVariableDeclaration(node)) { + each(node.declarations, function (declar) { + scope.push({ + kind: node.kind, + id: declar.id + }); + exprs.push(t.assignmentExpression("=", declar.id, declar.init)); + }); + } else if (t.isIfStatement(node)) { + return t.conditionalExpression( + node.test, + node.consequent ? t.toSequenceExpression([node.consequent]) : t.identifier("undefined"), + node.alternate ? t.toSequenceExpression([node.alternate]) : t.identifier("undefined") + ); + } else if (t.isBlockStatement(node)) { + return t.toSequenceExpression(node.body); + } + }); + + if (exprs.length === 1) { + return exprs[0]; + } else { + return t.sequenceExpression(exprs); + } +} + +/** + * Description + */ + +export function toKeyAlias(node: Object, key: Object = node.key) { + var alias; + if (t.isIdentifier(key)) { + alias = key.name; + } else if (t.isLiteral(key)) { + alias = JSON.stringify(key.value); + } else { + alias = JSON.stringify(traverse.removeProperties(t.cloneDeep(key))); + } + if (node.computed) alias = `[${alias}]`; + return alias; +} + +/* + * Description + */ + +export function toIdentifier(name: string): string { + if (t.isIdentifier(name)) return name.name; + + 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 || "_"; +} + +/** + * Description + * + * @returns {Object|Boolean} + */ + +export function toStatement(node: Object, ignore?: boolean) { + if (t.isStatement(node)) { + return node; + } + + var mustHaveId = false; + var 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; +} + +/** + * Description + */ + +export function toExpression(node: Object): Object { + if (t.isExpressionStatement(node)) { + node = node.expression; + } + + if (t.isClass(node)) { + node.type = "ClassExpression"; + } else if (t.isFunction(node)) { + node.type = "FunctionExpression"; + } + + if (t.isExpression(node)) { + return node; + } else { + throw new Error(`cannot turn ${node.type} to an expression`); + } +} + +/** + * Description + */ + +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); +} + +/** + * Description + */ + +export function valueToNode(value: any): Object { + if (value === undefined) { + return t.identifier("undefined"); + } + + if (value === true || value === false || value === null || isString(value) || isNumber(value) || isRegExp(value)) { + return t.literal(value); + } + + if (Array.isArray(value)) { + return t.arrayExpression(value.map(t.valueToNode)); + } + + if (isPlainObject(value)) { + var props = []; + for (var key in value) { + var nodeKey; + if (t.isValidIdentifier(key)) { + nodeKey = t.identifier(key); + } else { + nodeKey = t.literal(key); + } + props.push(t.property("init", 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/src/babel/types/evaluators.js b/src/babel/types/evaluators.js new file mode 100644 index 0000000000..163de2581e --- /dev/null +++ b/src/babel/types/evaluators.js @@ -0,0 +1,129 @@ +import * as t from "./index"; + +/** + * Walk the input `node` and statically evaluate if it's truthy. + * + * Returning `true` when we're sure that the expression will evaluate to a + * truthy value, `false` if we're sure that it will evaluate to a falsy + * value and `undefined` if we aren't sure. Because of this please do not + * rely on coercion when using this method and check with === if it's false. + * + * For example do: + * + * if (t.evaluateTruthy(node) === false) falsyLogic(); + * + * **AND NOT** + * + * if (!t.evaluateTruthy(node)) falsyLogic(); + * + */ + +export function evaluateTruthy(node: Object, scope: Scope): boolean { + var res = evaluate(node, scope); + if (res.confident) return !!res.value; +} + +/** + * Walk the input `node` and statically evaluate it. + * + * Returns an pbject in the form `{ confident, value }`. `confident` indicates + * whether or not we had to drop out of evaluating the expression because of + * hitting an unknown node that we couldn't confidently find the value of. + * + * Example: + * + * t.evaluate(parse("5 + 5")) // { confident: true, value: 10 } + * t.evaluate(parse("!true")) // { confident: true, value: false } + * t.evaluate(parse("foo + foo")) // { confident: false, value: undefined } + * + */ + +export function evaluate(node: Object, scope: Scope): { confident: boolean; value: any } { + var confident = true; + + var value = evaluate(node); + if (!confident) value = undefined; + return { + confident: confident, + value: value + }; + + function evaluate(node) { + if (!confident) return; + + if (t.isSequenceExpression(node)) { + return evaluate(node.expressions[node.expressions.length - 1]); + } + + if (t.isLiteral(node)) { + if (node.regex && node.value === null) { + // we have a regex and we can't represent it natively + } else { + return node.value; + } + } + + if (t.isConditionalExpression(node)) { + if (evaluate(node.test)) { + return evaluate(node.consequent); + } else { + return evaluate(node.alternate); + } + } + + if (t.isIdentifier(node)) { + if (node.name === "undefined") { + return undefined; + } else { + return evaluate(scope.getImmutableBindingValue(node.name)); + } + } + + if (t.isUnaryExpression(node, { prefix: true })) { + var arg = evaluate(node.argument); + switch (node.operator) { + case "void": return undefined; + case "!": return !arg; + case "+": return +arg; + case "-": return -arg; + } + } + + if (t.isArrayExpression(node) || t.isObjectExpression(node)) { + // we could evaluate these but it's probably impractical and not very useful + } + + if (t.isLogicalExpression(node)) { + let left = evaluate(node.left); + let right = evaluate(node.right); + + switch (node.operator) { + case "||": return left || right; + case "&&": return left && right; + } + } + + if (t.isBinaryExpression(node)) { + let left = evaluate(node.left); + let right = evaluate(node.right); + + switch (node.operator) { + case "-": return left - right; + case "+": return left + right; + case "/": return left / right; + case "*": return left * right; + case "%": return left % right; + case "<": return left < right; + case ">": return left > right; + case "<=": return left <= right; + case ">=": return left >= right; + case "==": return left == right; + case "!=": return left != right; + case "===": return left === right; + case "!==": return left !== right; + } + } + + confident = false; + } +} diff --git a/src/babel/types/index.js b/src/babel/types/index.js index 436b69dec0..dfbdf9b07e 100644 --- a/src/babel/types/index.js +++ b/src/babel/types/index.js @@ -1,17 +1,10 @@ import toFastProperties from "to-fast-properties"; -import isPlainObject from "lodash/lang/isPlainObject"; -import isNumber from "lodash/lang/isNumber"; -import isRegExp from "lodash/lang/isRegExp"; -import isString from "lodash/lang/isString"; import compact from "lodash/array/compact"; -import esutils from "esutils"; -import object from "../helpers/object"; -import clone from "lodash/lang/clone"; +import assign from "lodash/object/assign"; import each from "lodash/collection/each"; import uniq from "lodash/array/uniq"; -var t = {}; -export default t; +var t = exports; /** * Registers `is[Type]` and `assert[Type]` generated functions for a given `type`. @@ -31,13 +24,15 @@ function registerType(type: string, skipAliasCheck?: boolean) { }; } -t.STATEMENT_OR_BLOCK_KEYS = ["consequent", "body", "alternate"]; -t.NATIVE_TYPE_NAMES = ["Array", "Object", "Number", "Boolean", "Date", "Array", "String"]; -t.FLATTENABLE_KEYS = ["body", "expressions"]; -t.FOR_INIT_KEYS = ["left", "init"]; +export var STATEMENT_OR_BLOCK_KEYS = ["consequent", "body", "alternate"]; +export var NATIVE_TYPE_NAMES = ["Array", "Object", "Number", "Boolean", "Date", "Array", "String"]; +export var FLATTENABLE_KEYS = ["body", "expressions"]; +export var FOR_INIT_KEYS = ["left", "init"]; +export var COMMENT_KEYS = ["leadingComments", "trailingComments"]; -t.VISITOR_KEYS = require("./visitor-keys"); -t.ALIAS_KEYS = require("./alias-keys"); +export var VISITOR_KEYS = require("./visitor-keys"); +export var BUILDER_KEYS = require("./builder-keys"); +export var ALIAS_KEYS = require("./alias-keys"); t.FLIPPED_ALIAS_KEYS = {}; @@ -57,7 +52,7 @@ each(t.FLIPPED_ALIAS_KEYS, function (types, type) { registerType(type, false); }); -t.TYPES = Object.keys(t.VISITOR_KEYS).concat(Object.keys(t.FLIPPED_ALIAS_KEYS)); +export var TYPES = Object.keys(t.VISITOR_KEYS).concat(Object.keys(t.FLIPPED_ALIAS_KEYS)); /** * Returns whether `node` is of given `type`. @@ -66,7 +61,7 @@ t.TYPES = Object.keys(t.VISITOR_KEYS).concat(Object.keys(t.FLIPPED_ALIAS_KEYS)); * Optionally, pass `skipAliasCheck` to directly compare `node.type` with `type`. */ -t.is = function (type: string, node: Object, opts?: Object, skipAliasCheck?: boolean): boolean { +export function is(type: string, node: Object, opts?: Object, skipAliasCheck?: boolean): boolean { if (!node) return false; var typeMatches = type === node.type; @@ -88,11 +83,7 @@ t.is = function (type: string, node: Object, opts?: Object, skipAliasCheck?: boo } return true; -}; - -// - -t.BUILDER_KEYS = require("./builder-keys"); +} each(t.VISITOR_KEYS, function (keys, type) { if (t.BUILDER_KEYS[type]) return; @@ -122,65 +113,11 @@ each(t.BUILDER_KEYS, function (keys, type) { }; }); -/** - * Description - */ - -t.toComputedKey = function (node: Object, key: Object = node.key): Object { - if (!node.computed) { - if (t.isIdentifier(key)) key = t.literal(key.name); - } - return key; -}; - -/** - * 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. - */ - -t.toSequenceExpression = function (nodes: Array, scope: Scope): Object { - var exprs = []; - - each(nodes, function (node) { - if (t.isExpression(node)) { - exprs.push(node); - } if (t.isExpressionStatement(node)) { - exprs.push(node.expression); - } else if (t.isVariableDeclaration(node)) { - each(node.declarations, function (declar) { - scope.push({ - kind: node.kind, - id: declar.id - }); - exprs.push(t.assignmentExpression("=", declar.id, declar.init)); - }); - } else if (t.isIfStatement(node)) { - return t.conditionalExpression( - node.test, - node.consequent ? t.toSequenceExpression([node.consequent]) : t.identifier("undefined"), - node.alternate ? t.toSequenceExpression([node.alternate]) : t.identifier("undefined") - ); - } else if (t.isBlockStatement(node)) { - return t.toSequenceExpression(node.body); - } - }); - - if (exprs.length === 1) { - return exprs[0]; - } else { - return t.sequenceExpression(exprs); - } -}; - /* * Description */ -t.shallowEqual = function (actual: Object, expected: Object): boolean { +export function shallowEqual(actual: Object, expected: Object): boolean { var keys = Object.keys(expected); for (var i = 0; i < keys.length; i++) { @@ -192,204 +129,54 @@ t.shallowEqual = function (actual: Object, expected: Object): boolean { } return true; -}; +} /** * Description */ -t.appendToMemberExpression = function (member: Object, append: Object, computed?: boolean): Object { +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; -}; +} /** * Description */ -t.prependToMemberExpression = function (member: Object, append: Object): Object { +export function prependToMemberExpression(member: Object, append: Object): Object { member.object = t.memberExpression(append, member.object); return member; -}; - -/** - * Check if the input `node` is a reference to a bound variable. - */ - -t.isReferenced = function (node: Object, parent: Object): boolean { - // yes: PARENT[NODE] - // yes: NODE.child - // no: parent.CHILD - if (t.isMemberExpression(parent)) { - if (parent.property === node && parent.computed) { - return true; - } else if (parent.object === node) { - return true; - } else { - return false; - } - } - - // yes: { [NODE]: "" } - // no: { NODE: "" } - if (t.isProperty(parent) && parent.key === node) { - return parent.computed; - } - - // no: var NODE = init; - // yes: var id = NODE; - if (t.isVariableDeclarator(parent)) { - return parent.id !== node; - } - - // no: function NODE() {} - // no: function foo(NODE) {} - if (t.isFunction(parent)) { - for (var i = 0; i < parent.params.length; i++) { - var param = parent.params[i]; - if (param === node) return false; - } - - return parent.id !== node; - } - - // no: export { foo as NODE }; - if (t.isExportSpecifier(parent, { name: node })) { - return false; - } - - // no: import { NODE as foo } from "foo"; - if (t.isImportSpecifier(parent, { id: node })) { - return false; - } - - // no: class NODE {} - if (t.isClass(parent)) { - return parent.id !== node; - } - - // yes: class { [NODE](){} } - if (t.isMethodDefinition(parent)) { - return parent.key === node && parent.computed; - } - - // no: NODE: for (;;) {} - if (t.isLabeledStatement(parent)) { - return false; - } - - // no: try {} catch (NODE) {} - if (t.isCatchClause(parent)) { - return parent.param !== node; - } - - // no: function foo(...NODE) {} - if (t.isRestElement(parent)) { - return false; - } - - // no: [NODE = foo] = []; - // yes: [foo = NODE] = []; - if (t.isAssignmentPattern(parent)) { - return parent.right === node; - } - - // no: [NODE] = []; - // no: ({ NODE }) = []; - if (t.isPattern(parent)) { - return false; - } - - // no: import NODE from "bar"; - if (t.isImportSpecifier(parent)) { - return false; - } - - // no: import * as NODE from "foo"; - if (t.isImportBatchSpecifier(parent)) { - return false; - } - - // no: class Foo { private NODE; } - if (t.isPrivateDeclaration(parent)) { - return false; - } - - return true; -}; - -/** - * Check if the input `node` is an `Identifier` and `isReferenced`. - */ - -t.isReferencedIdentifier = function (node: Object, parent: Object, opts?: Object): boolean { - return t.isIdentifier(node, opts) && t.isReferenced(node, parent); -}; - -/** - * Check if the input `name` is a valid identifier name - * and isn't a reserved word. - */ - -t.isValidIdentifier = function (name: string): boolean { - return isString(name) && esutils.keyword.isIdentifierName(name) && !esutils.keyword.isReservedWordES6(name, true); -}; - -/* - * Description - */ - -t.toIdentifier = function (name: string): string { - if (t.isIdentifier(name)) return name.name; - - 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 || "_"; -}; +} /** * Description */ -t.ensureBlock = function (node: Object, key: string = "body") { +export function ensureBlock(node: Object, key: string = "body") { return node[key] = t.toBlock(node[key], node); -}; +} /** * Description */ -t.clone = function (node: Object): Object { +export function clone(node: Object): Object { var newNode = {}; for (var key in node) { if (key[0] === "_") continue; newNode[key] = node[key]; } return newNode; -}; +} /** * Description */ -t.cloneDeep = function (node: Object): Object { +export function cloneDeep(node: Object): Object { var newNode = {}; for (var key in node) { @@ -409,7 +196,7 @@ t.cloneDeep = function (node: Object): Object { } return newNode; -}; +} /** * Build a function that when called will return whether or not the @@ -419,7 +206,7 @@ t.cloneDeep = function (node: Object): Object { * parsed nodes of `React.createClass` and `React["createClass"]`. */ -t.buildMatchMemberExpression = function (match:string, allowPartial?: boolean): Function { +export function buildMatchMemberExpression(match:string, allowPartial?: boolean): Function { var parts = match.split("."); return function (member) { @@ -464,212 +251,35 @@ t.buildMatchMemberExpression = function (match:string, allowPartial?: boolean): return true; }; -}; - -/** - * Description - * - * @returns {Object|Boolean} - */ - -t.toStatement = function (node: Object, ignore?: boolean) { - if (t.isStatement(node)) { - return node; - } - - var mustHaveId = false; - var 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; -}; +} /** * Description */ -t.toExpression = function (node: Object): Object { - if (t.isExpressionStatement(node)) { - node = node.expression; - } - - if (t.isClass(node)) { - node.type = "ClassExpression"; - } else if (t.isFunction(node)) { - node.type = "FunctionExpression"; - } - - if (t.isExpression(node)) { - return node; - } else { - throw new Error(`cannot turn ${node.type} to an expression`); - } -}; - -/** - * Description - */ - -t.toBlock = function (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); -}; - -/** - * Return a list of binding identifiers associated with - * the input `node`. - */ - -t.getBindingIdentifiers = function (node: Object): Object { - var search = [].concat(node); - var ids = object(); - - while (search.length) { - var id = search.shift(); - if (!id) continue; - - var keys = t.getBindingIdentifiers.keys[id.type]; - - if (t.isIdentifier(id)) { - ids[id.name] = id; - } else if (t.isImportSpecifier(id)) { - search.push(id.name || id.id); - } else if (t.isExportDeclaration(id)) { - if (t.isDeclaration(node.declaration)) { - search.push(node.declaration); - } - } else if (keys) { - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - search = search.concat(id[key] || []); - } - } - } - - return ids; -}; - -t.getBindingIdentifiers.keys = { - UnaryExpression: ["argument"], - AssignmentExpression: ["left"], - ImportBatchSpecifier: ["name"], - VariableDeclarator: ["id"], - FunctionDeclaration: ["id"], - FunctionExpression: ["id"], - ClassDeclaration: ["id"], - ClassExpression: ["id"], - SpreadElement: ["argument"], - RestElement: ["argument"], - UpdateExpression: ["argument"], - SpreadProperty: ["argument"], - Property: ["value"], - ComprehensionBlock: ["left"], - AssignmentPattern: ["left"], - PrivateDeclaration: ["declarations"], - ComprehensionExpression: ["blocks"], - ImportDeclaration: ["specifiers"], - VariableDeclaration: ["declarations"], - ArrayPattern: ["elements"], - ObjectPattern: ["properties"] -}; - -/** - * Description - */ - -t.isLet = function (node: Object): boolean { - return t.isVariableDeclaration(node) && (node.kind !== "var" || node._let); -}; - -/** - * Description - */ - -t.isBlockScoped = function (node: Object): boolean { - return t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isLet(node); -}; - -/** - * Description - */ - -t.isVar = function (node: Object): boolean { - return t.isVariableDeclaration(node, { kind: "var" }) && !node._let; -}; - -// - -t.COMMENT_KEYS = ["leadingComments", "trailingComments"]; - -/** - * Description - */ - -t.removeComments = function (child: Object): Object { - each(t.COMMENT_KEYS, function (key) { +export function removeComments(child: Object): Object { + each(COMMENT_KEYS, function (key) { delete child[key]; }); return child; -}; +} /** * Description */ -t.inheritsComments = function (child: Object, parent: Object): Object { - each(t.COMMENT_KEYS, function (key) { +export function inheritsComments(child: Object, parent: Object): Object { + each(COMMENT_KEYS, function (key) { child[key] = uniq(compact([].concat(child[key], parent[key]))); }); return child; -}; +} /** * Description */ -t.inherits = function (child: Object, parent: Object): Object { +export function inherits(child: Object, parent: Object): Object { child._declarations = parent._declarations; child._scopeInfo = parent._scopeInfo; child.range = parent.range; @@ -682,283 +292,13 @@ t.inherits = function (child: Object, parent: Object): Object { t.inheritsComments(child, parent); return child; -}; - -/** - * Description - */ - -t.getLastStatements = function (node: Object): Array { - var nodes = []; - - var add = function (node) { - nodes = nodes.concat(t.getLastStatements(node)); - }; - - if (t.isIfStatement(node)) { - add(node.consequent); - add(node.alternate); - } else if (t.isFor(node) || t.isWhile(node)) { - add(node.body); - } else if (t.isProgram(node) || t.isBlockStatement(node)) { - add(node.body[node.body.length - 1]); - } else if (node) { - nodes.push(node); - } - - return nodes; -}; - -/** - * Description - */ - -t.toKeyAlias = function (node: Object, key: Object = node.key) { - var alias; - if (t.isIdentifier(key)) { - alias = key.name; - } else if (t.isLiteral(key)) { - alias = JSON.stringify(key.value); - } else { - alias = JSON.stringify(traverse.removeProperties(t.cloneDeep(key))); - } - if (node.computed) alias = `[${alias}]`; - return alias; -}; - -/** - * Description - */ - -t.getSpecifierName = function (specifier: Object): Object { - return specifier.name || specifier.id; -}; - -/** - * Description - */ - -t.getSpecifierId = function (specifier: Object): Object { - if (specifier.default) { - return t.identifier("default"); - } else { - return specifier.id; - } -}; - -/** - * Description - */ - -t.isSpecifierDefault = function (specifier: Object): boolean { - return specifier.default || t.isIdentifier(specifier.id) && specifier.id.name === "default"; -}; - -/** - * Description - */ - -t.isScope = function (node: Object, parent: Object): boolean { - if (t.isBlockStatement(node)) { - if (t.isLoop(parent.block, { body: node })) { - return false; - } - - if (t.isFunction(parent.block, { body: node })) { - return false; - } - } - - return t.isScopable(node); -}; - -/** - * Description - */ - -t.isImmutable = function (node: Object): boolean { - if (t.isLiteral(node)) { - if (node.regex) { - // regexes are mutable - return false; - } else { - // immutable! - return true; - } - } else if (t.isIdentifier(node)) { - if (node.name === "undefined") { - // immutable! - return true; - } else { - // no idea... - return false; - } - } - - return false; -}; - -/** - * Walk the input `node` and statically evaluate if it's truthy. - * - * Returning `true` when we're sure that the expression will evaluate to a - * truthy value, `false` if we're sure that it will evaluate to a falsy - * value and `undefined` if we aren't sure. Because of this please do not - * rely on coercion when using this method and check with === if it's false. - * - * For example do: - * - * if (t.evaluateTruthy(node) === false) falsyLogic(); - * - * **AND NOT** - * - * if (!t.evaluateTruthy(node)) falsyLogic(); - * - */ - -t.evaluateTruthy = function (node: Object, scope: Scope): boolean { - var res = t.evaluate(node, scope); - if (res.confident) return !!res.value; -}; - -/** - * Walk the input `node` and statically evaluate it. - * - * Returns an pbject in the form `{ confident, value }`. `confident` indicates - * whether or not we had to drop out of evaluating the expression because of - * hitting an unknown node that we couldn't confidently find the value of. - * - * Example: - * - * t.evaluate(parse("5 + 5")) // { confident: true, value: 10 } - * t.evaluate(parse("!true")) // { confident: true, value: false } - * t.evaluate(parse("foo + foo")) // { confident: false, value: undefined } - * - */ - -t.evaluate = function (node: Object, scope: Scope): { confident: boolean; value: any } { - var confident = true; - - var value = evaluate(node); - if (!confident) value = undefined; - return { - confident: confident, - value: value - }; - - function evaluate(node) { - if (!confident) return; - - if (t.isSequenceExpression(node)) { - return evaluate(node.expressions[node.expressions.length - 1]); - } - - if (t.isLiteral(node)) { - if (node.regex && node.value === null) { - // we have a regex and we can't represent it natively - } else { - return node.value; - } - } - - if (t.isConditionalExpression(node)) { - if (evaluate(node.test)) { - return evaluate(node.consequent); - } else { - return evaluate(node.alternate); - } - } - - if (t.isIdentifier(node)) { - if (node.name === "undefined") { - return undefined; - } else { - return evaluate(scope.getImmutableBindingValue(node.name)); - } - } - - if (t.isUnaryExpression(node, { prefix: true })) { - var arg = evaluate(node.argument); - switch (node.operator) { - case "void": return undefined; - case "!": return !arg; - case "+": return +arg; - case "-": return -arg; - } - } - - if (t.isArrayExpression(node) || t.isObjectExpression(node)) { - // we could evaluate these but it's probably impractical and not very useful - } - - if (t.isLogicalExpression(node)) { - var left = evaluate(node.left); - var right = evaluate(node.right); - - switch (node.operator) { - case "||": return left || right; - case "&&": return left && right; - } - } - - if (t.isBinaryExpression(node)) { - var left = evaluate(node.left); - var right = evaluate(node.right); - - switch (node.operator) { - case "-": return left - right; - case "+": return left + right; - case "/": return left / right; - case "*": return left * right; - case "%": return left % right; - case "<": return left < right; - case ">": return left > right; - case "<=": return left <= right; - case ">=": return left >= right; - case "==": return left == right; - case "!=": return left != right; - case "===": return left === right; - case "!==": return left !== right; - } - } - - confident = false; - } -}; - -/** - * Description - */ - -t.valueToNode = function (value: any): Object { - if (value === undefined) { - return t.identifier("undefined"); - } - - if (value === true || value === false || value === null || isString(value) || isNumber(value) || isRegExp(value)) { - return t.literal(value); - } - - if (Array.isArray(value)) { - return t.arrayExpression(value.map(t.valueToNode)); - } - - if (isPlainObject(value)) { - var props = []; - for (var key in value) { - var nodeKey; - if (t.isValidIdentifier(key)) { - nodeKey = t.identifier(key); - } else { - nodeKey = t.literal(key); - } - props.push(t.property("init", nodeKey, t.valueToNode(value[key]))); - } - return t.objectExpression(props); - } - - throw new Error("don't know how to turn this value into a node"); -}; +} toFastProperties(t); toFastProperties(t.VISITOR_KEYS); + +exports.__esModule = true; +assign(t, require("./evaluators")); +assign(t, require("./retrievers")); +assign(t, require("./validators")); +assign(t, require("./converters")); diff --git a/src/babel/types/retrievers.js b/src/babel/types/retrievers.js new file mode 100644 index 0000000000..ca0cfb3490 --- /dev/null +++ b/src/babel/types/retrievers.js @@ -0,0 +1,105 @@ +import object from "../helpers/object"; +import * as t from "./index"; + +/** + * Return a list of binding identifiers associated with + * the input `node`. + */ + +export function getBindingIdentifiers(node: Object): Object { + var search = [].concat(node); + var ids = object(); + + while (search.length) { + var id = search.shift(); + if (!id) continue; + + var keys = t.getBindingIdentifiers.keys[id.type]; + + if (t.isIdentifier(id)) { + ids[id.name] = id; + } else if (t.isImportSpecifier(id)) { + search.push(id.name || id.id); + } else if (t.isExportDeclaration(id)) { + if (t.isDeclaration(node.declaration)) { + search.push(node.declaration); + } + } else if (keys) { + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + search = search.concat(id[key] || []); + } + } + } + + return ids; +} + +getBindingIdentifiers.keys = { + UnaryExpression: ["argument"], + AssignmentExpression: ["left"], + ImportBatchSpecifier: ["name"], + VariableDeclarator: ["id"], + FunctionDeclaration: ["id"], + FunctionExpression: ["id"], + ClassDeclaration: ["id"], + ClassExpression: ["id"], + SpreadElement: ["argument"], + RestElement: ["argument"], + UpdateExpression: ["argument"], + SpreadProperty: ["argument"], + Property: ["value"], + ComprehensionBlock: ["left"], + AssignmentPattern: ["left"], + PrivateDeclaration: ["declarations"], + ComprehensionExpression: ["blocks"], + ImportDeclaration: ["specifiers"], + VariableDeclaration: ["declarations"], + ArrayPattern: ["elements"], + ObjectPattern: ["properties"] +}; + +/** + * Description + */ + +export function getLastStatements(node: Object): Array { + var nodes = []; + + var add = function (node) { + nodes = nodes.concat(getLastStatements(node)); + }; + + if (t.isIfStatement(node)) { + add(node.consequent); + add(node.alternate); + } else if (t.isFor(node) || t.isWhile(node)) { + add(node.body); + } else if (t.isProgram(node) || t.isBlockStatement(node)) { + add(node.body[node.body.length - 1]); + } else if (node) { + nodes.push(node); + } + + return nodes; +} + +/** + * Description + */ + +export function getSpecifierName(specifier: Object): Object { + return specifier.name || specifier.id; +} + +/** + * Description + */ + +export function getSpecifierId(specifier: Object): Object { + if (specifier.default) { + return t.identifier("default"); + } else { + return specifier.id; + } +} diff --git a/src/babel/types/validators.js b/src/babel/types/validators.js new file mode 100644 index 0000000000..4fac03d083 --- /dev/null +++ b/src/babel/types/validators.js @@ -0,0 +1,202 @@ +import isString from "lodash/lang/isString"; +import esutils from "esutils"; +import * as t from "./index"; + +/** + * Check if the input `node` is a reference to a bound variable. + */ + +export function isReferenced(node: Object, parent: Object): boolean { + // yes: PARENT[NODE] + // yes: NODE.child + // no: parent.CHILD + if (t.isMemberExpression(parent)) { + if (parent.property === node && parent.computed) { + return true; + } else if (parent.object === node) { + return true; + } else { + return false; + } + } + + // yes: { [NODE]: "" } + // no: { NODE: "" } + if (t.isProperty(parent) && parent.key === node) { + return parent.computed; + } + + // no: var NODE = init; + // yes: var id = NODE; + if (t.isVariableDeclarator(parent)) { + return parent.id !== node; + } + + // no: function NODE() {} + // no: function foo(NODE) {} + if (t.isFunction(parent)) { + for (var i = 0; i < parent.params.length; i++) { + var param = parent.params[i]; + if (param === node) return false; + } + + return parent.id !== node; + } + + // no: export { foo as NODE }; + if (t.isExportSpecifier(parent, { name: node })) { + return false; + } + + // no: import { NODE as foo } from "foo"; + if (t.isImportSpecifier(parent, { id: node })) { + return false; + } + + // no: class NODE {} + if (t.isClass(parent)) { + return parent.id !== node; + } + + // yes: class { [NODE](){} } + if (t.isMethodDefinition(parent)) { + return parent.key === node && parent.computed; + } + + // no: NODE: for (;;) {} + if (t.isLabeledStatement(parent)) { + return false; + } + + // no: try {} catch (NODE) {} + if (t.isCatchClause(parent)) { + return parent.param !== node; + } + + // no: function foo(...NODE) {} + if (t.isRestElement(parent)) { + return false; + } + + // no: [NODE = foo] = []; + // yes: [foo = NODE] = []; + if (t.isAssignmentPattern(parent)) { + return parent.right === node; + } + + // no: [NODE] = []; + // no: ({ NODE }) = []; + if (t.isPattern(parent)) { + return false; + } + + // no: import NODE from "bar"; + if (t.isImportSpecifier(parent)) { + return false; + } + + // no: import * as NODE from "foo"; + if (t.isImportBatchSpecifier(parent)) { + return false; + } + + // no: class Foo { private NODE; } + if (t.isPrivateDeclaration(parent)) { + return false; + } + + return true; +} + +/** + * Check if the input `node` is an `Identifier` and `isReferenced`. + */ + +export function isReferencedIdentifier(node: Object, parent: Object, opts?: Object): boolean { + return t.isIdentifier(node, opts) && t.isReferenced(node, parent); +} + +/** + * Check if the input `name` is a valid identifier name + * and isn't a reserved word. + */ + +export function isValidIdentifier(name: string): boolean { + return isString(name) && esutils.keyword.isIdentifierName(name) && !esutils.keyword.isReservedWordES6(name, true); +} + +/** + * Description + */ + +export function isLet(node: Object): boolean { + return t.isVariableDeclaration(node) && (node.kind !== "var" || node._let); +} + +/** + * Description + */ + +export function isBlockScoped(node: Object): boolean { + return t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isLet(node); +} + +/** + * Description + */ + +export function isVar(node: Object): boolean { + return t.isVariableDeclaration(node, { kind: "var" }) && !node._let; +} + +/** + * Description + */ + +export function isSpecifierDefault(specifier: Object): boolean { + return specifier.default || t.isIdentifier(specifier.id) && specifier.id.name === "default"; +} + +/** + * Description + */ + +export function isScope(node: Object, parent: Object): boolean { + if (t.isBlockStatement(node)) { + if (t.isLoop(parent.block, { body: node })) { + return false; + } + + if (t.isFunction(parent.block, { body: node })) { + return false; + } + } + + return t.isScopable(node); +} + +/** + * Description + */ + +export function isImmutable(node: Object): boolean { + if (t.isLiteral(node)) { + if (node.regex) { + // regexes are mutable + return false; + } else { + // immutable! + return true; + } + } else if (t.isIdentifier(node)) { + if (node.name === "undefined") { + // immutable! + return true; + } else { + // no idea... + return false; + } + } + + return false; +} diff --git a/src/babel/util.js b/src/babel/util.js index 56f83e5e6a..f9a8184639 100644 --- a/src/babel/util.js +++ b/src/babel/util.js @@ -14,7 +14,7 @@ import path from "path"; import each from "lodash/collection/each"; import has from "lodash/object/has"; import fs from "fs"; -import t from "./types"; +import * as t from "./types"; export { inherits, inspect } from "util"; diff --git a/test/fixtures/transformation/es6-classes/computed-methods/actual.js b/test/fixtures/transformation/es6-classes/computed-methods/actual.js index 86ad92a32a..fcc005f4be 100644 --- a/test/fixtures/transformation/es6-classes/computed-methods/actual.js +++ b/test/fixtures/transformation/es6-classes/computed-methods/actual.js @@ -2,4 +2,5 @@ class Foo { foo() {} "foo"() {} [bar]() {} + [bar + "foo"]() {} } diff --git a/test/fixtures/transformation/es6-classes/computed-methods/expected.js b/test/fixtures/transformation/es6-classes/computed-methods/expected.js index 0b344aa3d2..6ebadae9dc 100644 --- a/test/fixtures/transformation/es6-classes/computed-methods/expected.js +++ b/test/fixtures/transformation/es6-classes/computed-methods/expected.js @@ -14,6 +14,9 @@ var Foo = (function () { }, { key: bar, value: function () {} + }, { + key: bar + "foo", + value: function () {} }]); return Foo; })();