bloom-layout
Version:
layout components used in bloom packages
168 lines (147 loc) • 6.04 kB
JavaScript
/**
* @fileoverview Prevent usage of deprecated methods
* @author Yannick Croissant
* @author Scott Feeney
*/
;
const has = require('has');
const pragmaUtil = require('../util/pragma');
const versionUtil = require('../util/version');
const docsUrl = require('../util/docsUrl');
// ------------------------------------------------------------------------------
// Constants
// ------------------------------------------------------------------------------
const MODULES = {
react: ['React'],
'react-addons-perf': ['ReactPerf', 'Perf']
};
const DEPRECATED_MESSAGE = '{{oldMethod}} is deprecated since React {{version}}{{newMethod}}';
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
module.exports = {
meta: {
docs: {
description: 'Prevent usage of deprecated methods',
category: 'Best Practices',
recommended: true,
url: docsUrl('no-deprecated')
},
schema: []
},
create: function(context) {
const sourceCode = context.getSourceCode();
const pragma = pragmaUtil.getFromContext(context);
function getDeprecated() {
const deprecated = {};
// 0.12.0
deprecated[`${pragma}.renderComponent`] = ['0.12.0', `${pragma}.render`];
deprecated[`${pragma}.renderComponentToString`] = ['0.12.0', `${pragma}.renderToString`];
deprecated[`${pragma}.renderComponentToStaticMarkup`] = ['0.12.0', `${pragma}.renderToStaticMarkup`];
deprecated[`${pragma}.isValidComponent`] = ['0.12.0', `${pragma}.isValidElement`];
deprecated[`${pragma}.PropTypes.component`] = ['0.12.0', `${pragma}.PropTypes.element`];
deprecated[`${pragma}.PropTypes.renderable`] = ['0.12.0', `${pragma}.PropTypes.node`];
deprecated[`${pragma}.isValidClass`] = ['0.12.0'];
deprecated['this.transferPropsTo'] = ['0.12.0', 'spread operator ({...})'];
// 0.13.0
deprecated[`${pragma}.addons.classSet`] = ['0.13.0', 'the npm module classnames'];
deprecated[`${pragma}.addons.cloneWithProps`] = ['0.13.0', `${pragma}.cloneElement`];
// 0.14.0
deprecated[`${pragma}.render`] = ['0.14.0', 'ReactDOM.render'];
deprecated[`${pragma}.unmountComponentAtNode`] = ['0.14.0', 'ReactDOM.unmountComponentAtNode'];
deprecated[`${pragma}.findDOMNode`] = ['0.14.0', 'ReactDOM.findDOMNode'];
deprecated[`${pragma}.renderToString`] = ['0.14.0', 'ReactDOMServer.renderToString'];
deprecated[`${pragma}.renderToStaticMarkup`] = ['0.14.0', 'ReactDOMServer.renderToStaticMarkup'];
// 15.0.0
deprecated[`${pragma}.addons.LinkedStateMixin`] = ['15.0.0'];
deprecated['ReactPerf.printDOM'] = ['15.0.0', 'ReactPerf.printOperations'];
deprecated['Perf.printDOM'] = ['15.0.0', 'Perf.printOperations'];
deprecated['ReactPerf.getMeasurementsSummaryMap'] = ['15.0.0', 'ReactPerf.getWasted'];
deprecated['Perf.getMeasurementsSummaryMap'] = ['15.0.0', 'Perf.getWasted'];
// 15.5.0
deprecated[`${pragma}.createClass`] = ['15.5.0', 'the npm module create-react-class'];
deprecated[`${pragma}.addons.TestUtils`] = ['15.5.0', 'ReactDOM.TestUtils'];
deprecated[`${pragma}.PropTypes`] = ['15.5.0', 'the npm module prop-types'];
// 15.6.0
deprecated[`${pragma}.DOM`] = ['15.6.0', 'the npm module react-dom-factories'];
return deprecated;
}
function isDeprecated(method) {
const deprecated = getDeprecated();
return (
deprecated &&
deprecated[method] &&
versionUtil.testReactVersion(context, deprecated[method][0])
);
}
function checkDeprecation(node, method) {
if (!isDeprecated(method)) {
return;
}
const deprecated = getDeprecated();
context.report({
node: node,
message: DEPRECATED_MESSAGE,
data: {
oldMethod: method,
version: deprecated[method][0],
newMethod: deprecated[method][1] ? `, use ${deprecated[method][1]} instead` : ''
}
});
}
function getReactModuleName(node) {
let moduleName = false;
if (!node.init) {
return moduleName;
}
for (const module in MODULES) {
if (!has(MODULES, module)) {
continue;
}
moduleName = MODULES[module].find(name => name === node.init.name);
if (moduleName) {
break;
}
}
return moduleName;
}
// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------
return {
MemberExpression: function(node) {
checkDeprecation(node, sourceCode.getText(node));
},
ImportDeclaration: function(node) {
const isReactImport = typeof MODULES[node.source.value] !== 'undefined';
if (!isReactImport) {
return;
}
node.specifiers.forEach(specifier => {
if (!specifier.imported) {
return;
}
checkDeprecation(node, `${MODULES[node.source.value][0]}.${specifier.imported.name}`);
});
},
VariableDeclarator: function(node) {
const reactModuleName = getReactModuleName(node);
const isRequire = node.init && node.init.callee && node.init.callee.name === 'require';
const isReactRequire =
node.init && node.init.arguments &&
node.init.arguments.length && typeof MODULES[node.init.arguments[0].value] !== 'undefined'
;
const isDestructuring = node.id && node.id.type === 'ObjectPattern';
if (
!(isDestructuring && reactModuleName) &&
!(isDestructuring && isRequire && isReactRequire)
) {
return;
}
node.id.properties.forEach(property => {
checkDeprecation(node, `${reactModuleName || pragma}.${property.key.name}`);
});
}
};
}
};