source: imaps-frontend/node_modules/eslint-plugin-react/lib/rules/no-deprecated.js

main
Last change on this file was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 9.2 KB
Line 
1/**
2 * @fileoverview Prevent usage of deprecated methods
3 * @author Yannick Croissant
4 * @author Scott Feeney
5 * @author Sergei Startsev
6 */
7
8'use strict';
9
10const entries = require('object.entries');
11const astUtil = require('../util/ast');
12const componentUtil = require('../util/componentUtil');
13const docsUrl = require('../util/docsUrl');
14const pragmaUtil = require('../util/pragma');
15const testReactVersion = require('../util/version').testReactVersion;
16const report = require('../util/report');
17const getText = require('../util/eslint').getText;
18
19// ------------------------------------------------------------------------------
20// Constants
21// ------------------------------------------------------------------------------
22
23const MODULES = {
24 react: ['React'],
25 'react-addons-perf': ['ReactPerf', 'Perf'],
26 'react-dom': ['ReactDOM'],
27 'react-dom/server': ['ReactDOMServer'],
28};
29
30// ------------------------------------------------------------------------------
31// Rule Definition
32// ------------------------------------------------------------------------------
33
34function getDeprecated(pragma) {
35 const deprecated = {};
36 // 0.12.0
37 deprecated[`${pragma}.renderComponent`] = ['0.12.0', `${pragma}.render`];
38 deprecated[`${pragma}.renderComponentToString`] = ['0.12.0', `${pragma}.renderToString`];
39 deprecated[`${pragma}.renderComponentToStaticMarkup`] = ['0.12.0', `${pragma}.renderToStaticMarkup`];
40 deprecated[`${pragma}.isValidComponent`] = ['0.12.0', `${pragma}.isValidElement`];
41 deprecated[`${pragma}.PropTypes.component`] = ['0.12.0', `${pragma}.PropTypes.element`];
42 deprecated[`${pragma}.PropTypes.renderable`] = ['0.12.0', `${pragma}.PropTypes.node`];
43 deprecated[`${pragma}.isValidClass`] = ['0.12.0'];
44 deprecated['this.transferPropsTo'] = ['0.12.0', 'spread operator ({...})'];
45 // 0.13.0
46 deprecated[`${pragma}.addons.classSet`] = ['0.13.0', 'the npm module classnames'];
47 deprecated[`${pragma}.addons.cloneWithProps`] = ['0.13.0', `${pragma}.cloneElement`];
48 // 0.14.0
49 deprecated[`${pragma}.render`] = ['0.14.0', 'ReactDOM.render'];
50 deprecated[`${pragma}.unmountComponentAtNode`] = ['0.14.0', 'ReactDOM.unmountComponentAtNode'];
51 deprecated[`${pragma}.findDOMNode`] = ['0.14.0', 'ReactDOM.findDOMNode'];
52 deprecated[`${pragma}.renderToString`] = ['0.14.0', 'ReactDOMServer.renderToString'];
53 deprecated[`${pragma}.renderToStaticMarkup`] = ['0.14.0', 'ReactDOMServer.renderToStaticMarkup'];
54 // 15.0.0
55 deprecated[`${pragma}.addons.LinkedStateMixin`] = ['15.0.0'];
56 deprecated['ReactPerf.printDOM'] = ['15.0.0', 'ReactPerf.printOperations'];
57 deprecated['Perf.printDOM'] = ['15.0.0', 'Perf.printOperations'];
58 deprecated['ReactPerf.getMeasurementsSummaryMap'] = ['15.0.0', 'ReactPerf.getWasted'];
59 deprecated['Perf.getMeasurementsSummaryMap'] = ['15.0.0', 'Perf.getWasted'];
60 // 15.5.0
61 deprecated[`${pragma}.createClass`] = ['15.5.0', 'the npm module create-react-class'];
62 deprecated[`${pragma}.addons.TestUtils`] = ['15.5.0', 'ReactDOM.TestUtils'];
63 deprecated[`${pragma}.PropTypes`] = ['15.5.0', 'the npm module prop-types'];
64 // 15.6.0
65 deprecated[`${pragma}.DOM`] = ['15.6.0', 'the npm module react-dom-factories'];
66 // 16.9.0
67 // For now the following life-cycle methods are just legacy, not deprecated:
68 // `componentWillMount`, `componentWillReceiveProps`, `componentWillUpdate`
69 // https://github.com/yannickcr/eslint-plugin-react/pull/1750#issuecomment-425975934
70 deprecated.componentWillMount = [
71 '16.9.0',
72 'UNSAFE_componentWillMount',
73 'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. '
74 + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
75 ];
76 deprecated.componentWillReceiveProps = [
77 '16.9.0',
78 'UNSAFE_componentWillReceiveProps',
79 'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. '
80 + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
81 ];
82 deprecated.componentWillUpdate = [
83 '16.9.0',
84 'UNSAFE_componentWillUpdate',
85 'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. '
86 + 'Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
87 ];
88 // 18.0.0
89 // https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#deprecations
90 deprecated['ReactDOM.render'] = [
91 '18.0.0',
92 'createRoot',
93 'https://reactjs.org/link/switch-to-createroot',
94 ];
95 deprecated['ReactDOM.hydrate'] = [
96 '18.0.0',
97 'hydrateRoot',
98 'https://reactjs.org/link/switch-to-createroot',
99 ];
100 deprecated['ReactDOM.unmountComponentAtNode'] = [
101 '18.0.0',
102 'root.unmount',
103 'https://reactjs.org/link/switch-to-createroot',
104 ];
105 deprecated['ReactDOMServer.renderToNodeStream'] = [
106 '18.0.0',
107 'renderToPipeableStream',
108 'https://reactjs.org/docs/react-dom-server.html#rendertonodestream',
109 ];
110
111 return deprecated;
112}
113
114const messages = {
115 deprecated: '{{oldMethod}} is deprecated since React {{version}}{{newMethod}}{{refs}}',
116};
117
118module.exports = {
119 meta: {
120 docs: {
121 description: 'Disallow usage of deprecated methods',
122 category: 'Best Practices',
123 recommended: true,
124 url: docsUrl('no-deprecated'),
125 },
126
127 messages,
128
129 schema: [],
130 },
131
132 create(context) {
133 const pragma = pragmaUtil.getFromContext(context);
134 const deprecated = getDeprecated(pragma);
135
136 function isDeprecated(method) {
137 return (
138 deprecated
139 && deprecated[method]
140 && deprecated[method][0]
141 && testReactVersion(context, `>= ${deprecated[method][0]}`)
142 );
143 }
144
145 function checkDeprecation(node, methodName, methodNode) {
146 if (!isDeprecated(methodName)) {
147 return;
148 }
149 const version = deprecated[methodName][0];
150 const newMethod = deprecated[methodName][1];
151 const refs = deprecated[methodName][2];
152 report(context, messages.deprecated, 'deprecated', {
153 node: methodNode || node,
154 data: {
155 oldMethod: methodName,
156 version,
157 newMethod: newMethod ? `, use ${newMethod} instead` : '',
158 refs: refs ? `, see ${refs}` : '',
159 },
160 });
161 }
162
163 function getReactModuleName(node) {
164 let moduleName = false;
165 if (!node.init) {
166 return false;
167 }
168
169 entries(MODULES).some((entry) => {
170 const key = entry[0];
171 const moduleNames = entry[1];
172 if (
173 node.init.arguments
174 && node.init.arguments.length > 0
175 && node.init.arguments[0]
176 && key === node.init.arguments[0].value
177 ) {
178 moduleName = MODULES[key][0];
179 } else {
180 moduleName = moduleNames.find((name) => name === node.init.name);
181 }
182 return moduleName;
183 });
184
185 return moduleName;
186 }
187
188 /**
189 * Returns life cycle methods if available
190 * @param {ASTNode} node The AST node being checked.
191 * @returns {Array} The array of methods.
192 */
193 function getLifeCycleMethods(node) {
194 const properties = astUtil.getComponentProperties(node);
195 return properties.map((property) => ({
196 name: astUtil.getPropertyName(property),
197 node: astUtil.getPropertyNameNode(property),
198 }));
199 }
200
201 /**
202 * Checks life cycle methods
203 * @param {ASTNode} node The AST node being checked.
204 */
205 function checkLifeCycleMethods(node) {
206 if (
207 componentUtil.isES5Component(node, context)
208 || componentUtil.isES6Component(node, context)
209 ) {
210 const methods = getLifeCycleMethods(node);
211 methods.forEach((method) => checkDeprecation(node, method.name, method.node));
212 }
213 }
214
215 // --------------------------------------------------------------------------
216 // Public
217 // --------------------------------------------------------------------------
218
219 return {
220 MemberExpression(node) {
221 checkDeprecation(node, getText(context, node));
222 },
223
224 ImportDeclaration(node) {
225 const isReactImport = typeof MODULES[node.source.value] !== 'undefined';
226 if (!isReactImport) {
227 return;
228 }
229 node.specifiers.filter(((s) => s.imported)).forEach((specifier) => {
230 checkDeprecation(node, `${MODULES[node.source.value][0]}.${specifier.imported.name}`, specifier);
231 });
232 },
233
234 VariableDeclarator(node) {
235 const reactModuleName = getReactModuleName(node);
236 const isRequire = node.init && node.init.callee && node.init.callee.name === 'require';
237 const isReactRequire = node.init
238 && node.init.arguments
239 && node.init.arguments.length
240 && typeof MODULES[node.init.arguments[0].value] !== 'undefined';
241 const isDestructuring = node.id && node.id.type === 'ObjectPattern';
242
243 if (
244 !(isDestructuring && reactModuleName)
245 && !(isDestructuring && isRequire && isReactRequire)
246 ) {
247 return;
248 }
249 node.id.properties.filter((p) => p.type !== 'RestElement' && p.key).forEach((property) => {
250 checkDeprecation(node, `${reactModuleName || pragma}.${property.key.name}`, property);
251 });
252 },
253
254 ClassDeclaration: checkLifeCycleMethods,
255 ClassExpression: checkLifeCycleMethods,
256 ObjectExpression: checkLifeCycleMethods,
257 };
258 },
259};
Note: See TracBrowser for help on using the repository browser.