UNPKG

@typescript-eslint/eslint-plugin

Version:
150 lines • 6.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const scope_manager_1 = require("@typescript-eslint/scope-manager"); const utils_1 = require("@typescript-eslint/utils"); const util_1 = require("../util"); const UNNECESSARY_OPERATORS = new Set(['=', '&&=', '||=', '??=']); exports.default = (0, util_1.createRule)({ name: 'no-unnecessary-parameter-property-assignment', meta: { docs: { description: 'Disallow unnecessary assignment of constructor property parameter', }, messages: { unnecessaryAssign: 'This assignment is unnecessary since it is already assigned by a parameter property.', }, schema: [], type: 'suggestion', }, defaultOptions: [], create(context) { const reportInfoStack = []; function isThisMemberExpression(node) { return (node.type === utils_1.AST_NODE_TYPES.MemberExpression && node.object.type === utils_1.AST_NODE_TYPES.ThisExpression); } function getPropertyName(node) { if (!isThisMemberExpression(node)) { return null; } if (node.property.type === utils_1.AST_NODE_TYPES.Identifier) { return node.property.name; } if (node.computed) { return (0, util_1.getStaticStringValue)(node.property); } return null; } function findParentFunction(node) { if (!node || node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration || node.type === utils_1.AST_NODE_TYPES.FunctionExpression || node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { return node; } return findParentFunction(node.parent); } function findParentPropertyDefinition(node) { if (!node || node.type === utils_1.AST_NODE_TYPES.PropertyDefinition) { return node; } return findParentPropertyDefinition(node.parent); } function isConstructorFunctionExpression(node) { return (node?.type === utils_1.AST_NODE_TYPES.FunctionExpression && utils_1.ASTUtils.isConstructor(node.parent)); } function isReferenceFromParameter(node) { const scope = context.sourceCode.getScope(node); const rightRef = scope.references.find(ref => ref.identifier.name === node.name); return rightRef?.resolved?.defs.at(0)?.type === scope_manager_1.DefinitionType.Parameter; } function isParameterPropertyWithName(node, name) { return (node.type === utils_1.AST_NODE_TYPES.TSParameterProperty && ((node.parameter.type === utils_1.AST_NODE_TYPES.Identifier && // constructor (public foo) {} node.parameter.name === name) || (node.parameter.type === utils_1.AST_NODE_TYPES.AssignmentPattern && // constructor (public foo = 1) {} node.parameter.left.type === utils_1.AST_NODE_TYPES.Identifier && node.parameter.left.name === name))); } function getIdentifier(node) { if (node.type === utils_1.AST_NODE_TYPES.Identifier) { return node; } if (node.type === utils_1.AST_NODE_TYPES.TSAsExpression || node.type === utils_1.AST_NODE_TYPES.TSNonNullExpression) { return getIdentifier(node.expression); } return null; } function isArrowIIFE(node) { return (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression && node.parent.type === utils_1.AST_NODE_TYPES.CallExpression); } return { ClassBody() { reportInfoStack.push({ unnecessaryAssignments: [], assignedBeforeUnnecessary: new Set(), assignedBeforeConstructor: new Set(), }); }, 'ClassBody:exit'() { const { unnecessaryAssignments, assignedBeforeConstructor } = (0, util_1.nullThrows)(reportInfoStack.pop(), 'The top stack should exist'); unnecessaryAssignments.forEach(({ name, node }) => { if (assignedBeforeConstructor.has(name)) { return; } context.report({ node, messageId: 'unnecessaryAssign', }); }); }, 'PropertyDefinition AssignmentExpression'(node) { const name = getPropertyName(node.left); if (!name) { return; } const functionNode = findParentFunction(node); if (functionNode && !(isArrowIIFE(functionNode) && findParentPropertyDefinition(node)?.value === functionNode.parent)) { return; } const { assignedBeforeConstructor } = (0, util_1.nullThrows)(reportInfoStack.at(-1), 'The top stack should exist'); assignedBeforeConstructor.add(name); }, "MethodDefinition[kind='constructor'] > FunctionExpression AssignmentExpression"(node) { const leftName = getPropertyName(node.left); if (!leftName) { return; } let functionNode = findParentFunction(node); if (functionNode && isArrowIIFE(functionNode)) { functionNode = findParentFunction(functionNode.parent); } if (!isConstructorFunctionExpression(functionNode)) { return; } const { assignedBeforeUnnecessary, unnecessaryAssignments } = (0, util_1.nullThrows)(reportInfoStack.at(reportInfoStack.length - 1), 'The top of stack should exist'); if (!UNNECESSARY_OPERATORS.has(node.operator)) { assignedBeforeUnnecessary.add(leftName); return; } const rightId = getIdentifier(node.right); if (leftName !== rightId?.name || !isReferenceFromParameter(rightId)) { return; } const hasParameterProperty = functionNode.params.some(param => isParameterPropertyWithName(param, rightId.name)); if (hasParameterProperty && !assignedBeforeUnnecessary.has(leftName)) { unnecessaryAssignments.push({ name: leftName, node, }); } }, }; }, }); //# sourceMappingURL=no-unnecessary-parameter-property-assignment.js.map