UNPKG

extjs-replace-callparent

Version:

Replace Ext JS `callParent` calls with direct method calls on parent class

167 lines (132 loc) 7.38 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.default = initDefinitionFactory; function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Definition Module * * This file contains the code for finding the parent `Ext.define` or `Ext.override` definition for a `callParent` call. */ function initDefinitionFactory(t) { function isCalleeExtDefine(callee) { return t.isIdentifier(callee.property, { name: 'define' }); } function isCalleeExtOverride(callee) { return t.isIdentifier(callee.property, { name: 'override' }); } function isDefinition(extNames) { extNames = extNames || ['Ext']; return function isDefinition(path) { if (!path.isCallExpression()) { return false; } var callee = path.node.callee; return t.isMemberExpression(callee) && t.isIdentifier(callee.object) && extNames.includes(callee.object.name) && (isCalleeExtDefine(callee) || isCalleeExtOverride(callee)); }; } function getProtoPropFromObjectExpression(objectExpression) { return objectExpression.properties.find(function (prop) { return t.isIdentifier(prop.key) && (prop.key.name === 'extend' || prop.key.name === 'override'); }); } var returnStatementVisitor = { ReturnStatement: function ReturnStatement(path, state) { if (!path.findParent(function (p) { return p.isFunctionExpression(); }) === state.functionExpression) { return; } path.stop(); // we've found the return statement, stop traversal var returnArg = path.get('argument'); if (!returnArg.isObjectExpression()) { return; } state.returnArg = returnArg.node; } }; function getFunctionDefineReturnObjectExpression(functionExpression) { var nestedVisitorState = { functionExpression: functionExpression, returnArg: null }; functionExpression.traverse(returnStatementVisitor, nestedVisitorState); return nestedVisitorState.returnArg; } function getDefineProtoProp(bodyArg) { if (bodyArg.isObjectExpression()) { return getProtoPropFromObjectExpression(bodyArg.node); } else if (bodyArg.isFunctionExpression()) { var objectExpression = getFunctionDefineReturnObjectExpression(bodyArg); if (!objectExpression) { return; } return getProtoPropFromObjectExpression(objectExpression); } } function buildMemberExpression(stringRef) { return stringRef.split('.').reduce(function (last, next) { return last ? t.memberExpression(last, t.identifier(next)) : t.identifier(next); }, null); } function getPrototypeRef(prototypeValue) { return t.isStringLiteral(prototypeValue) ? buildMemberExpression(prototypeValue.value) : prototypeValue; } var AbstractDefinition = function () { function AbstractDefinition(path) { _classCallCheck(this, AbstractDefinition); this.path = path; } _createClass(AbstractDefinition, [{ key: 'prependVariableRef', value: function prependVariableRef(value) { var refVar = this.path.scope.generateUidIdentifier('o'); this.path.insertBefore(t.variableDeclaration('var', [t.variableDeclarator(refVar, value)])); return refVar; } }]); return AbstractDefinition; }(); var DefineDefinition = function (_AbstractDefinition) { _inherits(DefineDefinition, _AbstractDefinition); function DefineDefinition(path) { _classCallCheck(this, DefineDefinition); var _this = _possibleConstructorReturn(this, (DefineDefinition.__proto__ || Object.getPrototypeOf(DefineDefinition)).call(this, path)); var bodyArg = path.get('arguments.1'); var protoProp = getDefineProtoProp(bodyArg); _this.protoRef = protoProp ? getPrototypeRef(protoProp.value) : buildMemberExpression('Ext.Base'); _this.isOverride = protoProp && protoProp.key.name === 'override'; return _this; } return DefineDefinition; }(AbstractDefinition); var OverrideDefinition = function (_AbstractDefinition2) { _inherits(OverrideDefinition, _AbstractDefinition2); function OverrideDefinition(path) { _classCallCheck(this, OverrideDefinition); var _this2 = _possibleConstructorReturn(this, (OverrideDefinition.__proto__ || Object.getPrototypeOf(OverrideDefinition)).call(this, path)); var prototypeValue = path.get('arguments.0').node; _this2.protoRef = getPrototypeRef(prototypeValue); _this2.isOverride = true; return _this2; } return OverrideDefinition; }(AbstractDefinition); /** * Find the `Ext.define` or `Ext.override` definition * * If the `callParent` call is within an `Ext.define`, then a `DefineDefinition` is returned * If the `callParent` call is within an `Ext.override`, then a `OverrideDefinition` is returned * * In either case, they expose `protoRef`, `isOverride` properties, and a `createPrependedVariableRef` method which * is used for prepending the reference to the overriden method when the definition is overriding a class. */ return function findParentDefinition(childPath, extNames) { var path = childPath.findParent(isDefinition(extNames)); if (!path) { throw childPath.buildCodeFrameError("Unable to find 'Ext.define' or 'Ext.override' for this 'callParent'"); } return isCalleeExtOverride(path.node.callee) ? new OverrideDefinition(path) : new DefineDefinition(path); }; }