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

main
Last change on this file since 0c6b92a was 0c6b92a, checked in by stefan toskovski <stefantoska84@…>, 5 weeks ago

Pred finalna verzija

  • Property mode set to 100644
File size: 9.7 KB
RevLine 
[d565449]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
[0c6b92a]118/** @type {import('eslint').Rule.RuleModule} */
[d565449]119module.exports = {
120 meta: {
121 docs: {
122 description: 'Disallow usage of deprecated methods',
123 category: 'Best Practices',
124 recommended: true,
125 url: docsUrl('no-deprecated'),
126 },
127
128 messages,
129
130 schema: [],
131 },
132
133 create(context) {
134 const pragma = pragmaUtil.getFromContext(context);
135 const deprecated = getDeprecated(pragma);
136
137 function isDeprecated(method) {
138 return (
139 deprecated
140 && deprecated[method]
141 && deprecated[method][0]
142 && testReactVersion(context, `>= ${deprecated[method][0]}`)
143 );
144 }
145
146 function checkDeprecation(node, methodName, methodNode) {
147 if (!isDeprecated(methodName)) {
148 return;
149 }
150 const version = deprecated[methodName][0];
151 const newMethod = deprecated[methodName][1];
152 const refs = deprecated[methodName][2];
153 report(context, messages.deprecated, 'deprecated', {
154 node: methodNode || node,
155 data: {
156 oldMethod: methodName,
157 version,
158 newMethod: newMethod ? `, use ${newMethod} instead` : '',
159 refs: refs ? `, see ${refs}` : '',
160 },
161 });
162 }
163
164 function getReactModuleName(node) {
165 let moduleName = false;
166 if (!node.init) {
167 return false;
168 }
169
170 entries(MODULES).some((entry) => {
171 const key = entry[0];
172 const moduleNames = entry[1];
173 if (
174 node.init.arguments
175 && node.init.arguments.length > 0
176 && node.init.arguments[0]
177 && key === node.init.arguments[0].value
178 ) {
179 moduleName = MODULES[key][0];
180 } else {
181 moduleName = moduleNames.find((name) => name === node.init.name);
182 }
183 return moduleName;
184 });
185
186 return moduleName;
187 }
188
189 /**
190 * Returns life cycle methods if available
191 * @param {ASTNode} node The AST node being checked.
192 * @returns {Array} The array of methods.
193 */
194 function getLifeCycleMethods(node) {
195 const properties = astUtil.getComponentProperties(node);
196 return properties.map((property) => ({
197 name: astUtil.getPropertyName(property),
198 node: astUtil.getPropertyNameNode(property),
199 }));
200 }
201
202 /**
203 * Checks life cycle methods
204 * @param {ASTNode} node The AST node being checked.
205 */
206 function checkLifeCycleMethods(node) {
207 if (
208 componentUtil.isES5Component(node, context)
209 || componentUtil.isES6Component(node, context)
210 ) {
211 const methods = getLifeCycleMethods(node);
212 methods.forEach((method) => checkDeprecation(node, method.name, method.node));
213 }
214 }
215
216 // --------------------------------------------------------------------------
217 // Public
218 // --------------------------------------------------------------------------
219
220 return {
221 MemberExpression(node) {
222 checkDeprecation(node, getText(context, node));
223 },
224
225 ImportDeclaration(node) {
226 const isReactImport = typeof MODULES[node.source.value] !== 'undefined';
227 if (!isReactImport) {
228 return;
229 }
[0c6b92a]230 node.specifiers.filter(((s) => 'imported' in s && s.imported)).forEach((specifier) => {
231 // TODO, semver-major: remove `in` check as part of jsdoc->tsdoc migration
232 checkDeprecation(node, 'imported' in specifier && `${MODULES[node.source.value][0]}.${specifier.imported.name}`, specifier);
[d565449]233 });
234 },
235
236 VariableDeclarator(node) {
237 const reactModuleName = getReactModuleName(node);
[0c6b92a]238 const isRequire = node.init
239 && 'callee' in node.init
240 && node.init.callee
241 && 'name' in node.init.callee
242 && node.init.callee.name === 'require';
[d565449]243 const isReactRequire = node.init
[0c6b92a]244 && 'arguments' in node.init
[d565449]245 && node.init.arguments
246 && node.init.arguments.length
[0c6b92a]247 && typeof MODULES['value' in node.init.arguments[0] ? node.init.arguments[0].value : undefined] !== 'undefined';
[d565449]248 const isDestructuring = node.id && node.id.type === 'ObjectPattern';
249
250 if (
251 !(isDestructuring && reactModuleName)
252 && !(isDestructuring && isRequire && isReactRequire)
253 ) {
254 return;
255 }
[0c6b92a]256
257 ('properties' in node.id ? node.id.properties : undefined).filter((p) => p.type !== 'RestElement' && p.key).forEach((property) => {
258 checkDeprecation(
259 node,
260 'key' in property && 'name' in property.key && `${reactModuleName || pragma}.${property.key.name}`,
261 property
262 );
[d565449]263 });
264 },
265
266 ClassDeclaration: checkLifeCycleMethods,
267 ClassExpression: checkLifeCycleMethods,
268 ObjectExpression: checkLifeCycleMethods,
269 };
270 },
271};
Note: See TracBrowser for help on using the repository browser.