d2-ui
Version:
276 lines (218 loc) • 6.79 kB
JavaScript
"use strict";
exports.__esModule = true;
var _getIterator2 = require("babel-runtime/core-js/get-iterator");
var _getIterator3 = _interopRequireDefault(_getIterator2);
exports.isBinding = isBinding;
exports.isReferenced = isReferenced;
exports.isValidIdentifier = isValidIdentifier;
exports.isLet = isLet;
exports.isBlockScoped = isBlockScoped;
exports.isVar = isVar;
exports.isSpecifierDefault = isSpecifierDefault;
exports.isScope = isScope;
exports.isImmutable = isImmutable;
var _retrievers = require("./retrievers");
var _esutils = require("esutils");
var _esutils2 = _interopRequireDefault(_esutils);
var _index = require("./index");
var t = _interopRequireWildcard(_index);
var _constants = require("./constants");
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Check if the input `node` is a binding identifier.
*/
/* eslint indent: 0 */
function isBinding(node, parent) {
var keys = _retrievers.getBindingIdentifiers.keys[parent.type];
if (keys) {
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var 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.
*/
function isReferenced(node, parent) {
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 (var _iterator = parent.params, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var param = _ref;
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: <div NODE="foo" />
case "JSXAttribute":
return parent.name !== node;
// no: class { NODE = value; }
// yes: class { key = NODE; }
case "ClassProperty":
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.
*/
function isValidIdentifier(name) {
if (typeof name !== "string" || _esutils2.default.keyword.isReservedWordES6(name, true)) {
return false;
} else {
return _esutils2.default.keyword.isIdentifierNameES6(name);
}
}
/**
* Check if the input `node` is a `let` variable declaration.
*/
function isLet(node) {
return t.isVariableDeclaration(node) && (node.kind !== "var" || node[_constants.BLOCK_SCOPED_SYMBOL]);
}
/**
* Check if the input `node` is block scoped.
*/
function isBlockScoped(node) {
return t.isFunctionDeclaration(node) || t.isClassDeclaration(node) || t.isLet(node);
}
/**
* Check if the input `node` is a variable declaration.
*/
function isVar(node) {
return t.isVariableDeclaration(node, { kind: "var" }) && !node[_constants.BLOCK_SCOPED_SYMBOL];
}
/**
* Check if the input `specifier` is a `default` import or export.
*/
function isSpecifierDefault(specifier) {
return t.isImportDefaultSpecifier(specifier) || t.isIdentifier(specifier.imported || specifier.exported, { name: "default" });
}
/**
* Check if the input `node` is a scope.
*/
function isScope(node, parent) {
if (t.isBlockStatement(node) && t.isFunction(parent, { body: node })) {
return false;
}
return t.isScopable(node);
}
/**
* Check if the input `node` is definitely immutable.
*/
function isImmutable(node) {
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;
}