From 8d9ba7506f11421db73cba35271cf9deed428b7c Mon Sep 17 00:00:00 2001 From: Sergei Startsev Date: Sun, 1 Apr 2018 22:31:15 +0300 Subject: [PATCH] Added `refs` field to refer to docs in`no-deprecated` rule, minor adjustments --- lib/rules/no-deprecated.js | 36 ++-- tests/lib/rules/no-deprecated.js | 282 +++++++++++++++++-------------- 2 files changed, 178 insertions(+), 140 deletions(-) diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js index 0e332b7eb2..53d4a1299c 100644 --- a/lib/rules/no-deprecated.js +++ b/lib/rules/no-deprecated.js @@ -23,7 +23,7 @@ const MODULES = { 'react-addons-perf': ['ReactPerf', 'Perf'] }; -const DEPRECATED_MESSAGE = '{{oldMethod}} is deprecated since React {{version}}{{newMethod}}'; +const DEPRECATED_MESSAGE = '{{oldMethod}} is deprecated since React {{version}}{{newMethod}}{{refs}}'; // ------------------------------------------------------------------------------ // Rule Definition @@ -77,9 +77,21 @@ module.exports = { // 15.6.0 deprecated[`${pragma}.DOM`] = ['15.6.0', 'the npm module react-dom-factories']; // 16.3.0 - deprecated.componentWillMount = ['16.3.0']; - deprecated.componentWillReceiveProps = ['16.3.0']; - deprecated.componentWillUpdate = ['16.3.0']; + deprecated.componentWillMount = [ + '16.3.0', + 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ]; + deprecated.componentWillReceiveProps = [ + '16.3.0', + 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ]; + deprecated.componentWillUpdate = [ + '16.3.0', + 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ]; return deprecated; } @@ -98,13 +110,17 @@ module.exports = { return; } const deprecated = getDeprecated(); + const version = deprecated[method][0]; + const newMethod = deprecated[method][1]; + const refs = deprecated[method][2]; context.report({ node: node, message: DEPRECATED_MESSAGE, data: { oldMethod: method, - version: deprecated[method][0], - newMethod: deprecated[method][1] ? `, use ${deprecated[method][1]} instead` : '' + version, + newMethod: newMethod ? `, use ${newMethod} instead` : '', + refs: refs ? `, see ${refs}` : '' } }); } @@ -153,11 +169,11 @@ module.exports = { return { - MemberExpression: function(node) { + MemberExpression: function (node) { checkDeprecation(node, sourceCode.getText(node)); }, - ImportDeclaration: function(node) { + ImportDeclaration: function (node) { const isReactImport = typeof MODULES[node.source.value] !== 'undefined'; if (!isReactImport) { return; @@ -170,13 +186,13 @@ module.exports = { }); }, - VariableDeclarator: function(node) { + 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 ( diff --git a/tests/lib/rules/no-deprecated.js b/tests/lib/rules/no-deprecated.js index 8e589f219d..f52fc766b6 100644 --- a/tests/lib/rules/no-deprecated.js +++ b/tests/lib/rules/no-deprecated.js @@ -24,11 +24,10 @@ const parserOptions = { require('babel-eslint'); -function errorMessage(oldMethod, version, newMethod) { - if (!newMethod) { - newMethod = ''; - } - return `${oldMethod} is deprecated since React ${version}${newMethod}`; +function errorMessage(oldMethod, version, newMethod, refs) { + newMethod = newMethod ? `, use ${newMethod} instead` : ''; + refs = refs ? `, see ${refs}` : ''; + return `${oldMethod} is deprecated since React ${version}${newMethod}${refs}`; } // ------------------------------------------------------------------------------ @@ -101,129 +100,87 @@ ruleTester.run('no-deprecated', rule, { invalid: [ { code: 'React.renderComponent()', - settings: {react: {version: '0.12.0'}}, - errors: [{ - message: 'React.renderComponent is deprecated since React 0.12.0, use React.render instead' - }] + errors: [{message: errorMessage('React.renderComponent', '0.12.0', 'React.render')}] }, { code: 'Foo.renderComponent()', - settings: {react: {pragma: 'Foo', version: '0.12.0'}}, - errors: [{ - message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' - }] + settings: {react: {pragma: 'Foo'}}, + errors: [{message: errorMessage('Foo.renderComponent', '0.12.0', 'Foo.render')}] }, { code: '/** @jsx Foo */ Foo.renderComponent()', - settings: {react: {version: '0.12.0'}}, - errors: [{ - message: 'Foo.renderComponent is deprecated since React 0.12.0, use Foo.render instead' - }] + errors: [{message: errorMessage('Foo.renderComponent', '0.12.0', 'Foo.render')}] }, { code: 'this.transferPropsTo()', - errors: [{ - message: 'this.transferPropsTo is deprecated since React 0.12.0, use spread operator ({...}) instead' - }] + errors: [{message: errorMessage('this.transferPropsTo', '0.12.0', 'spread operator ({...})')}] }, { code: 'React.addons.TestUtils', - errors: [{ - message: 'React.addons.TestUtils is deprecated since React 15.5.0, use ReactDOM.TestUtils instead' - }] + errors: [{message: errorMessage('React.addons.TestUtils', '15.5.0', 'ReactDOM.TestUtils')}] }, { code: 'React.addons.classSet()', - errors: [{ - message: 'React.addons.classSet is deprecated since React 0.13.0, use the npm module classnames instead' - }] + errors: [{message: errorMessage('React.addons.classSet', '0.13.0', 'the npm module classnames')}] }, { code: 'React.render(element, container);', - errors: [{ - message: 'React.render is deprecated since React 0.14.0, use ReactDOM.render instead' - }] + errors: [{message: errorMessage('React.render', '0.14.0', 'ReactDOM.render')}] }, { code: 'React.unmountComponentAtNode(container);', - errors: [{ - message: ( - 'React.unmountComponentAtNode is deprecated since React 0.14.0, ' + - 'use ReactDOM.unmountComponentAtNode instead' - ) - }] + errors: [{message: errorMessage('React.unmountComponentAtNode', '0.14.0', 'ReactDOM.unmountComponentAtNode')}] }, { code: 'React.findDOMNode(instance);', - errors: [{ - message: 'React.findDOMNode is deprecated since React 0.14.0, use ReactDOM.findDOMNode instead' - }] + errors: [{message: errorMessage('React.findDOMNode', '0.14.0', 'ReactDOM.findDOMNode')}] }, { code: 'React.renderToString(element);', - errors: [{ - message: 'React.renderToString is deprecated since React 0.14.0, use ReactDOMServer.renderToString instead' - }] + errors: [{message: errorMessage('React.renderToString', '0.14.0', 'ReactDOMServer.renderToString')}] }, { code: 'React.renderToStaticMarkup(element);', - errors: [{ - message: ( - 'React.renderToStaticMarkup is deprecated since React 0.14.0, ' + - 'use ReactDOMServer.renderToStaticMarkup instead' - ) - }] + errors: [{message: errorMessage('React.renderToStaticMarkup', '0.14.0', 'ReactDOMServer.renderToStaticMarkup')}] }, { code: 'React.createClass({});', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'Foo.createClass({});', settings: {react: {pragma: 'Foo'}}, - errors: [{ - message: 'Foo.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('Foo.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'React.PropTypes', - errors: [{ - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [{message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')}] }, { code: 'var {createClass} = require(\'react\');', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'var {createClass, PropTypes} = require(\'react\');', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [ + {message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}, + {message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')} + ] }, { code: 'import {createClass} from \'react\';', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }] + errors: [{message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}] }, { code: 'import {createClass, PropTypes} from \'react\';', parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [ + {message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}, + {message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')} + ] }, { code: ` @@ -231,34 +188,27 @@ ruleTester.run('no-deprecated', rule, { const {createClass, PropTypes} = React; `, parser: 'babel-eslint', - errors: [{ - message: 'React.createClass is deprecated since React 15.5.0, use the npm module create-react-class instead' - }, { - message: 'React.PropTypes is deprecated since React 15.5.0, use the npm module prop-types instead' - }] + errors: [ + {message: errorMessage('React.createClass', '15.5.0', 'the npm module create-react-class')}, + {message: errorMessage('React.PropTypes', '15.5.0', 'the npm module prop-types')} + ] }, { code: 'import {printDOM} from \'react-addons-perf\';', parser: 'babel-eslint', - errors: [{ - message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' - }] + errors: [{message: errorMessage('ReactPerf.printDOM', '15.0.0', 'ReactPerf.printOperations')}] }, { code: ` - import ReactPerf from 'react-addons-perf'; - const {printDOM} = ReactPerf; - `, + import ReactPerf from 'react-addons-perf'; + const {printDOM} = ReactPerf; + `, parser: 'babel-eslint', - errors: [{ - message: 'ReactPerf.printDOM is deprecated since React 15.0.0, use ReactPerf.printOperations instead' - }] + errors: [{message: errorMessage('ReactPerf.printDOM', '15.0.0', 'ReactPerf.printOperations')}] }, { code: 'React.DOM.div', - errors: [{ - message: 'React.DOM is deprecated since React 15.6.0, use the npm module react-dom-factories instead' - }] + errors: [{message: errorMessage('React.DOM', '15.6.0', 'the npm module react-dom-factories')}] }, { code: ` @@ -268,13 +218,25 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} }; `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -286,13 +248,25 @@ ruleTester.run('no-deprecated', rule, { }; } `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -302,13 +276,25 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} }; `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -318,13 +304,25 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} } `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` @@ -334,29 +332,53 @@ ruleTester.run('no-deprecated', rule, { componentWillUpdate() {} } `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] }, { code: ` - var Foo = createReactClass({ - componentWillMount: function() {}, - componentWillReceiveProps: function() {}, - componentWillUpdate: function() {} - }) + var Foo = createReactClass({ + componentWillMount: function() {}, + componentWillReceiveProps: function() {}, + componentWillUpdate: function() {} + }) `, - settings: {react: {version: '16.3.0'}}, errors: [ - {message: errorMessage('componentWillMount', '16.3.0')}, - {message: errorMessage('componentWillReceiveProps', '16.3.0')}, - {message: errorMessage('componentWillUpdate', '16.3.0')} - ], - parserOptions: parserOptions + { + message: errorMessage( + 'componentWillMount', '16.3.0', 'constructor', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount' + ) + }, + { + message: errorMessage( + 'componentWillReceiveProps', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops' + ) + }, + { + message: errorMessage('componentWillUpdate', '16.3.0', 'getDerivedStateFromProps', + 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate' + ) + } + ] } ] });