escomplex-plugin-syntax-babylon
Version:
Provides a plugin for typhonjs-escomplex module processing which loads syntax definitions for trait resolution for Babylon AST.
396 lines (323 loc) • 15.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray');
var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _PluginSyntaxESTree2 = require('escomplex-plugin-syntax-estree/dist/PluginSyntaxESTree');
var _PluginSyntaxESTree3 = _interopRequireDefault(_PluginSyntaxESTree2);
var _ASTGenerator = require('typhonjs-escomplex-commons/dist/utils/ast/ASTGenerator');
var _ASTGenerator2 = _interopRequireDefault(_ASTGenerator);
var _HalsteadArray = require('typhonjs-escomplex-commons/dist/module/traits/HalsteadArray');
var _HalsteadArray2 = _interopRequireDefault(_HalsteadArray);
var _TraitUtil = require('typhonjs-escomplex-commons/dist/module/traits/TraitUtil');
var _TraitUtil2 = _interopRequireDefault(_TraitUtil);
var _actualize = require('typhonjs-escomplex-commons/dist/module/traits/actualize');
var _actualize2 = _interopRequireDefault(_actualize);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Provides an typhonjs-escomplex-module / ESComplexModule plugin which loads syntax definitions for trait resolution
* for unique Babylon AST not found in ESTree.
*
* @see https://www.npmjs.com/package/typhonjs-escomplex-module
*/
var PluginSyntaxBabylon = function (_PluginSyntaxESTree) {
(0, _inherits3.default)(PluginSyntaxBabylon, _PluginSyntaxESTree);
function PluginSyntaxBabylon() {
(0, _classCallCheck3.default)(this, PluginSyntaxBabylon);
return (0, _possibleConstructorReturn3.default)(this, (PluginSyntaxBabylon.__proto__ || (0, _getPrototypeOf2.default)(PluginSyntaxBabylon)).apply(this, arguments));
}
(0, _createClass3.default)(PluginSyntaxBabylon, [{
key: 'BindExpression',
// Unique Babylon AST nodes --------------------------------------------------------------------------------------
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#bindexpression
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
value: function BindExpression() {
return (0, _actualize2.default)(0, 0);
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#booleanliteral
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'BooleanLiteral',
value: function BooleanLiteral() {
return (0, _actualize2.default)(0, 0, undefined, function (node) {
return node.value;
});
}
// /**
// * @see https://github.com/babel/babylon/blob/master/ast/spec.md#classmethod
// * @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
// */
// ClassMethod()
// {
// return actualize(1, 0, (node) =>
// {
// const operators = typeof node.computed === 'boolean' && node.computed ?
// [...ASTGenerator.parse(node.key).operators] : [];
//
// if (node.kind && (node.kind === 'get' || node.kind === 'set')) { operators.push(node.kind); }
// if (typeof node.async === 'boolean' && node.async) { operators.push('async'); }
// if (typeof node.static === 'boolean' && node.static) { operators.push('static'); }
//
// if (typeof node.generator === 'boolean' && node.generator)
// {
// operators.push('function*');
// }
//
// return operators;
// },
// (node, parent) => { return s_SAFE_COMPUTED_OPERANDS(node, parent); },
// 'key', // Note: must skip key as the assigned name is determined above.
// (node) =>
// {
// let name;
//
// if (typeof node.computed === 'boolean' && node.computed)
// {
// name = node.key.type === 'StringLiteral' ? TraitUtil.safeValue(node.key) :
// `<computed~${ASTGenerator.parse(node.key).source}>`;
// }
// else // ClassMethod is not computed and is an `Identifier` node.
// {
// name = TraitUtil.safeName(node.key);
// }
//
// return {
// type: 'method',
// name,
// lineStart: node.loc.start.line,
// lineEnd: node.loc.end.line,
// paramCount: node.params.length
// };
// });
// }
/**
* Note: logical SLOC for the method declaration should be incremented by the module metric processor.
*
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#classmethod
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'ClassMethod',
value: function ClassMethod() {
return (0, _actualize2.default)(0, 0, void 0, void 0, ['key', 'params'], // Note: skip key & params as name / operands / operators are calculated in new scope below.
function (node, parent) {
var name = void 0;
var operands = [];
var operators = [];
if (node.kind && (node.kind === 'get' || node.kind === 'set')) {
operators.push(node.kind);
}
if (typeof node.async === 'boolean' && node.async) {
operators.push('async');
}
if (typeof node.static === 'boolean' && node.static) {
operators.push('static');
}
if (typeof node.generator === 'boolean' && node.generator) {
operators.push('function*');
}
// Calculate method declaration name
if (typeof node.computed === 'boolean' && node.computed) {
name = node.key.type === 'StringLiteral' ? _TraitUtil2.default.safeValue(node.key) : '<computed~' + _ASTGenerator2.default.parse(node.key).source + '>';
operands.push.apply(operands, (0, _toConsumableArray3.default)(s_SAFE_COMPUTED_OPERANDS(node, parent)));
operators.push.apply(operators, (0, _toConsumableArray3.default)(_ASTGenerator2.default.parse(node.key).operators));
} else // ClassMethod is not computed and is an `Identifier` node.
{
name = _TraitUtil2.default.safeName(node.key);
operands.push(name);
}
var paramNames = [];
// Parse params; must use ASTGenerator
if (Array.isArray(node.params)) {
node.params.forEach(function (param) {
var parsedParams = _ASTGenerator2.default.parse(param);
operands.push.apply(operands, (0, _toConsumableArray3.default)(parsedParams.operands));
operators.push.apply(operators, (0, _toConsumableArray3.default)(parsedParams.operators));
// For param names only the left hand node of AssignmentPattern must be considered.
if (param.type === 'AssignmentPattern') {
paramNames.push.apply(paramNames, (0, _toConsumableArray3.default)(_ASTGenerator2.default.parse(param.left).operands));
} else {
paramNames.push.apply(paramNames, (0, _toConsumableArray3.default)(parsedParams.operands));
}
});
}
return {
type: 'method',
name: name,
cyclomatic: 1,
lineStart: node.loc.start.line,
lineEnd: node.loc.end.line,
lloc: 1,
operands: new _HalsteadArray2.default('operands', operands),
operators: new _HalsteadArray2.default('operators', operators),
paramNames: paramNames
};
});
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#decorator
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'Decorator',
value: function Decorator() {
return (0, _actualize2.default)(0, 0);
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#directive
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'Directive',
value: function Directive() {
return (0, _actualize2.default)(1, 0);
}
/**
* Avoid conflicts between string literals and identifiers.
*
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#directiveliteral
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'DirectiveLiteral',
value: function DirectiveLiteral() {
return (0, _actualize2.default)(0, 0, void 0, function (node) {
return typeof node.value === 'string' ? '"' + node.value + '"' : node.value;
});
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#nullliteral
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'NullLiteral',
value: function NullLiteral() {
return (0, _actualize2.default)(0, 0, void 0, 'null');
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#numericliteral
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'NumericLiteral',
value: function NumericLiteral() {
return (0, _actualize2.default)(0, 0, void 0, function (node) {
return node.value;
});
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#objectmethod
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'ObjectMethod',
value: function ObjectMethod() {
return (0, _actualize2.default)(1, 0, function (node) {
return typeof node.kind === 'string' && (node.kind === 'get' || node.kind === 'set') ? node.kind : void 0;
}, void 0, 'key'); // Note: must skip key as the assigned name is forwarded on to FunctionExpression.
}
/**
* Note: that w/ ES6+ `:` may be omitted and the Property node defines `shorthand` to indicate this case.
*
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#objectproperty
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'ObjectProperty',
value: function ObjectProperty() {
return (0, _actualize2.default)(1, 0, function (node) {
return typeof node.shorthand === 'undefined' ? ':' : typeof node.shorthand === 'boolean' && !node.shorthand ? ':' : void 0;
});
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#regexpliteral
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'RegExpLiteral',
value: function RegExpLiteral() {
return (0, _actualize2.default)(0, 0, void 0, function (node) {
var operands = [];
if ((0, _typeof3.default)(node.extra) === 'object' && typeof node.extra.raw !== 'undefined') {
operands.push(node.extra.raw);
}
return operands;
});
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#restproperty
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'RestProperty',
value: function RestProperty() {
return (0, _actualize2.default)(0, 0, '... (rest)');
}
/**
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#spreadproperty
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'SpreadProperty',
value: function SpreadProperty() {
return (0, _actualize2.default)(0, 0, '... (spread)');
}
/**
* Avoid conflicts between string literals and identifiers.
*
* @see https://github.com/babel/babylon/blob/master/ast/spec.md#stringliteral
* @returns {{lloc: *, cyclomatic: *, operators: *, operands: *, ignoreKeys: *, newScope: *, dependencies: *}}
*/
}, {
key: 'StringLiteral',
value: function StringLiteral() {
return (0, _actualize2.default)(0, 0, void 0, function (node) {
return '"' + node.value + '"';
});
}
}]);
return PluginSyntaxBabylon;
}(_PluginSyntaxESTree3.default);
/**
* Provides a utility method that determines the operands of a method for Babylon AST nodes. If the name is a computed
* value and not a string literal then `ASTGenerator` is invoked to determine the computed operands.
*
* @param {object} node - The current AST node.
*
* @returns {Array<*>}
*/
exports.default = PluginSyntaxBabylon;
function s_SAFE_COMPUTED_OPERANDS(node) {
var operands = [];
if (typeof node.computed === 'boolean' && node.computed) {
// The following will pick up a single literal computed value (string).
if (node.key.type === 'StringLiteral') {
operands.push(_TraitUtil2.default.safeValue(node.key));
} else // Fully evaluate AST node and children for computed operands.
{
operands.push.apply(operands, (0, _toConsumableArray3.default)(_ASTGenerator2.default.parse(node.key).operands));
}
} else // Parent is not computed and `parent.key` is an `Identifier` node.
{
operands.push(_TraitUtil2.default.safeName(node.key));
}
return operands;
}
module.exports = exports['default'];