| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 | 'use strict';const {hasSideEffect, isParenthesized, findVariable} = require('@eslint-community/eslint-utils');const {matches, methodCallSelector} = require('../selectors/index.js');const isFunctionSelfUsedInside = require('../utils/is-function-self-used-inside.js');const getBinaryExpressionSelector = path => [	`[${path}.type="BinaryExpression"]`,	`[${path}.operator="==="]`,	`:matches([${path}.left.type="Identifier"], [${path}.right.type="Identifier"])`,].join('');const getFunctionSelector = path => [	`[${path}.generator!=true]`,	`[${path}.async!=true]`,	`[${path}.params.length=1]`,	`[${path}.params.0.type="Identifier"]`,].join('');const callbackFunctionSelector = path => matches([	// Matches `foo.findIndex(bar => bar === baz)`	[		`[${path}.type="ArrowFunctionExpression"]`,		getFunctionSelector(path),		getBinaryExpressionSelector(`${path}.body`),	].join(''),	// Matches `foo.findIndex(bar => {return bar === baz})`	// Matches `foo.findIndex(function (bar) {return bar === baz})`	[		`:matches([${path}.type="ArrowFunctionExpression"], [${path}.type="FunctionExpression"])`,		getFunctionSelector(path),		`[${path}.body.type="BlockStatement"]`,		`[${path}.body.body.length=1]`,		`[${path}.body.body.0.type="ReturnStatement"]`,		getBinaryExpressionSelector(`${path}.body.body.0.argument`),	].join(''),]);const isIdentifierNamed = ({type, name}, expectName) => type === 'Identifier' && name === expectName;function simpleArraySearchRule({method, replacement}) {	// Add prefix to avoid conflicts in `prefer-includes` rule	const MESSAGE_ID_PREFIX = `prefer-${replacement}-over-${method}/`;	const ERROR = `${MESSAGE_ID_PREFIX}error`;	const SUGGESTION = `${MESSAGE_ID_PREFIX}suggestion`;	const ERROR_MESSAGES = {		findIndex: 'Use `.indexOf()` instead of `.findIndex()` when looking for the index of an item.',		findLastIndex: 'Use `.lastIndexOf()` instead of `findLastIndex() when looking for the index of an item.`',		some: `Use \`.${replacement}()\` instead of \`.${method}()\` when checking value existence.`,	};	const messages = {		[ERROR]: ERROR_MESSAGES[method],		[SUGGESTION]: `Replace \`.${method}()\` with \`.${replacement}()\`.`,	};	const selector = [		methodCallSelector({			method,			argumentsLength: 1,		}),		callbackFunctionSelector('arguments.0'),	].join('');	function createListeners(context) {		const sourceCode = context.getSourceCode();		const {scopeManager} = sourceCode;		return {			[selector](node) {				const [callback] = node.arguments;				const binaryExpression = callback.body.type === 'BinaryExpression'					? callback.body					: callback.body.body[0].argument;				const [parameter] = callback.params;				const {left, right} = binaryExpression;				const {name} = parameter;				let searchValueNode;				let parameterInBinaryExpression;				if (isIdentifierNamed(left, name)) {					searchValueNode = right;					parameterInBinaryExpression = left;				} else if (isIdentifierNamed(right, name)) {					searchValueNode = left;					parameterInBinaryExpression = right;				} else {					return;				}				const callbackScope = scopeManager.acquire(callback);				if (					// `parameter` is used somewhere else					findVariable(callbackScope, parameter).references.some(({identifier}) => identifier !== parameterInBinaryExpression)					|| isFunctionSelfUsedInside(callback, callbackScope)				) {					return;				}				const method = node.callee.property;				const problem = {					node: method,					messageId: ERROR,					suggest: [],				};				const fix = function * (fixer) {					let text = sourceCode.getText(searchValueNode);					if (isParenthesized(searchValueNode, sourceCode) && !isParenthesized(callback, sourceCode)) {						text = `(${text})`;					}					yield fixer.replaceText(method, replacement);					yield fixer.replaceText(callback, text);				};				if (hasSideEffect(searchValueNode, sourceCode)) {					problem.suggest.push({messageId: SUGGESTION, fix});				} else {					problem.fix = fix;				}				return problem;			},		};	}	return {messages, createListeners};}module.exports = simpleArraySearchRule;
 |