diff --git a/eslint-plugin-expensify/prefer-at.js b/eslint-plugin-expensify/prefer-at.js index 0e92f7d..c7c1056 100644 --- a/eslint-plugin-expensify/prefer-at.js +++ b/eslint-plugin-expensify/prefer-at.js @@ -1,6 +1,8 @@ const { AST_NODE_TYPES, ESLintUtils } = require('@typescript-eslint/utils'); const message = require('./CONST').MESSAGE.PREFER_AT; +const { isLeftHandSide } = require('./utils/is-left-hand-side'); + module.exports = { meta: { fixable: 'code', @@ -73,6 +75,16 @@ module.exports = { return; } + // Skip if the property is a method (like a?.map) + if (node.parent && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node) { + return; + } + + // Skip if the node is part of an assignment expression + if (isLeftHandSide(node)) { + return; + } + const indexExpression = parseExpression(node.property); if (indexExpression !== null && indexExpression !== 'length' && indexExpression !== 'at') { diff --git a/eslint-plugin-expensify/tests/prefer-at.test.js b/eslint-plugin-expensify/tests/prefer-at.test.js index dd65f76..84e3e4f 100644 --- a/eslint-plugin-expensify/tests/prefer-at.test.js +++ b/eslint-plugin-expensify/tests/prefer-at.test.js @@ -66,6 +66,12 @@ ruleTester.run('prefer-at', rule, { { code: 'const a = ["a", "b", "c"] as const; a[0]', }, + { + code: 'const example = [1, 2, 3, 4]; example.map(x => x * 2);', + }, + { + code: 'const example = [1, 2, 3, 4]; const x = 1; example[x] = 5;', + }, ], invalid: [ { diff --git a/eslint-plugin-expensify/utils/is-left-hand-side.js b/eslint-plugin-expensify/utils/is-left-hand-side.js new file mode 100644 index 0000000..6b03b32 --- /dev/null +++ b/eslint-plugin-expensify/utils/is-left-hand-side.js @@ -0,0 +1,27 @@ +// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/rules/utils/is-left-hand-side.js + +const { AST_NODE_TYPES } = require('@typescript-eslint/utils'); + +function isLeftHandSide(node) { + const { parent } = node; + + return ( + (parent.type === AST_NODE_TYPES.AssignmentExpression || parent.type === AST_NODE_TYPES.AssignmentPattern) + && parent.left === node + ) + || (parent.type === AST_NODE_TYPES.UpdateExpression && parent.argument === node) + || (parent.type === AST_NODE_TYPES.ArrayPattern && parent.elements.includes(node)) + || ( + parent.type === AST_NODE_TYPES.Property + && parent.value === node + && parent.parent.type === AST_NODE_TYPES.ObjectPattern + && parent.parent.properties.includes(parent) + ) + || ( + parent.type === AST_NODE_TYPES.UnaryExpression + && parent.operator === 'delete' + && parent.argument === node + ); +} + +module.exports = { isLeftHandSide };