@masknet/eslint-plugin
Version:
eslint plugin for masknet
71 lines • 2.52 kB
JavaScript
import { isIdentifier, isMemberExpression } from '../../node.js';
import { createRule } from '../../rule.js';
const CLASS_NAMES = new Set(['PureComponent', 'Component']);
const EXEMPT_FIELDS = new Set(['getDerivedStateFromError']);
export default createRule({
name: 'jsx/no-class-component',
meta: {
type: 'problem',
docs: {
description: 'Disallow React Class Component',
recommended: 'stylistic',
},
schema: [],
messages: {
invalid: 'Disallow React Class Component',
},
},
create(context) {
return {
ImportDeclaration(node) {
if (node.source.value !== 'react')
return;
const references = node.specifiers
.flatMap((importClause) => {
if (context.sourceCode.scopeManager) {
return context.sourceCode.scopeManager.getDeclaredVariables(importClause);
}
return [];
})
.flatMap((variable) => variable.references)
.filter(isReactComponentReference);
for (const reference of references) {
context.report({
node: reference.from.block,
messageId: 'invalid',
});
}
},
};
},
});
function isReactComponentReference({ isValueReference, identifier, resolved, from }) {
if (!isValueReference || from.type !== 'class')
return false;
if (!isDefinitionGood(resolved))
return false;
if (isExempt(from.block.body))
return false;
if (CLASS_NAMES.has(identifier.name))
return true;
return (isMemberExpression(identifier.parent) &&
isIdentifier(identifier.parent.property) &&
CLASS_NAMES.has(identifier.parent.property.name));
}
function isExempt({ body }) {
// prettier-ignore
return body.some((element) => ("key" in element &&
element.static &&
element.key.type === "Identifier" &&
EXEMPT_FIELDS.has(element.key.name)));
}
function isDefinitionGood(variable) {
return variable?.defs.every(({ node }) => {
if (node.type === 'ImportDefaultSpecifier')
return true;
if (node.type === 'ImportSpecifier')
return CLASS_NAMES.has(node.imported.name);
return false;
});
}
//# sourceMappingURL=no-class-component.js.map