Build NapCat Artifacts / Windows Loader Test (push) Canceled after 0s
Build NapCat Artifacts / Type Check & Test (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Framework (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Shell (push) Canceled after 0s
142 lines
3.6 KiB
Plaintext
142 lines
3.6 KiB
Plaintext
/**
|
|
* @fileoverview Forbid using another component's propTypes
|
|
* @author Ian Christian Myers
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const docsUrl = require('../util/docsUrl');
|
|
const ast = require('../util/ast');
|
|
const report = require('../util/report');
|
|
|
|
const messages = {
|
|
forbiddenPropType: 'Using propTypes from another component is not safe because they may be removed in production builds',
|
|
};
|
|
|
|
/** @type {import('eslint').Rule.RuleModule} */
|
|
module.exports = {
|
|
meta: {
|
|
docs: {
|
|
description: 'Disallow using another component\'s propTypes',
|
|
category: 'Best Practices',
|
|
recommended: false,
|
|
url: docsUrl('forbid-foreign-prop-types'),
|
|
},
|
|
|
|
messages,
|
|
|
|
schema: [
|
|
{
|
|
type: 'object',
|
|
properties: {
|
|
allowInPropTypes: {
|
|
type: 'boolean',
|
|
},
|
|
},
|
|
additionalProperties: false,
|
|
},
|
|
],
|
|
},
|
|
|
|
create(context) {
|
|
const config = context.options[0] || {};
|
|
const allowInPropTypes = config.allowInPropTypes || false;
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Helpers
|
|
// --------------------------------------------------------------------------
|
|
|
|
function findParentAssignmentExpression(node) {
|
|
let parent = node.parent;
|
|
|
|
while (parent && parent.type !== 'Program') {
|
|
if (parent.type === 'AssignmentExpression') {
|
|
return parent;
|
|
}
|
|
parent = parent.parent;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function findParentClassProperty(node) {
|
|
let parent = node.parent;
|
|
|
|
while (parent && parent.type !== 'Program') {
|
|
if (parent.type === 'ClassProperty' || parent.type === 'PropertyDefinition') {
|
|
return parent;
|
|
}
|
|
parent = parent.parent;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function isAllowedAssignment(node) {
|
|
if (!allowInPropTypes) {
|
|
return false;
|
|
}
|
|
|
|
const assignmentExpression = findParentAssignmentExpression(node);
|
|
|
|
if (
|
|
assignmentExpression
|
|
&& assignmentExpression.left
|
|
&& assignmentExpression.left.property
|
|
&& assignmentExpression.left.property.name === 'propTypes'
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const classProperty = findParentClassProperty(node);
|
|
|
|
if (
|
|
classProperty
|
|
&& classProperty.key
|
|
&& classProperty.key.name === 'propTypes'
|
|
) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return {
|
|
MemberExpression(node) {
|
|
if (
|
|
(node.property
|
|
&& (
|
|
!node.computed
|
|
&& node.property.type === 'Identifier'
|
|
&& node.property.name === 'propTypes'
|
|
&& !ast.isAssignmentLHS(node)
|
|
&& !isAllowedAssignment(node)
|
|
)) || (
|
|
// @ts-expect-error: The JSXText type is not present in the estree type definitions
|
|
(node.property.type === 'Literal' || node.property.type === 'JSXText')
|
|
&& 'value' in node.property
|
|
&& node.property.value === 'propTypes'
|
|
&& !ast.isAssignmentLHS(node)
|
|
&& !isAllowedAssignment(node)
|
|
)
|
|
) {
|
|
report(context, messages.forbiddenPropType, 'forbiddenPropType', {
|
|
node: node.property,
|
|
});
|
|
}
|
|
},
|
|
|
|
ObjectPattern(node) {
|
|
const propTypesNode = node.properties.find((property) => (
|
|
property.type === 'Property'
|
|
&& 'name' in property.key
|
|
&& property.key.name === 'propTypes'
|
|
));
|
|
|
|
if (propTypesNode) {
|
|
report(context, messages.forbiddenPropType, 'forbiddenPropType', {
|
|
node: propTypesNode,
|
|
});
|
|
}
|
|
},
|
|
};
|
|
},
|
|
};
|