diff --git a/lib/rules/no-get.js b/lib/rules/no-get.js index 38a59ce9f3..f686aa09eb 100644 --- a/lib/rules/no-get.js +++ b/lib/rules/no-get.js @@ -28,11 +28,15 @@ const ERROR_MESSAGE_GET_PROPERTIES = "Use `{ prop1: this.prop1, prop2: this.prop2, ... }` instead of Ember's `getProperties` function"; const VALID_JS_VARIABLE_NAME_REGEXP = new RegExp('^[a-zA-Z_$][0-9a-zA-Z_$]*$'); +const VALID_JS_ARRAY_INDEX_REGEXP = new RegExp(/^\d+$/); function isValidJSVariableName(str) { return VALID_JS_VARIABLE_NAME_REGEXP.test(str); } +function isValidJSArrayIndex(str) { + return VALID_JS_ARRAY_INDEX_REGEXP.test(str); +} function isValidJSPath(str) { - return str.split('.').every(isValidJSVariableName); + return str.split('.').every((part) => isValidJSVariableName(part) || isValidJSArrayIndex(part)); } function reportGet({ node, context, path, isImportedGet, useOptionalChaining }) { @@ -62,7 +66,13 @@ function fixGet({ node, fixer, path, useOptionalChaining, isInLeftSideOfAssignme } // In the left side of an assignment, we can safely autofix nested paths without using optional chaining. - const replacementPath = isInLeftSideOfAssignmentExpression ? path : path.replace(/\./g, '?.'); + let replacementPath = isInLeftSideOfAssignmentExpression ? path : path.replace(/\./g, '?.'); + + // Replace any array element access (foo.1 => foo[1] or foo?.[1]). + replacementPath = replacementPath.replace( + /\.(\d+)/g, + isInLeftSideOfAssignmentExpression ? '[$1]' : '.[$1]' + ); return fixer.replaceText(node, `this.${replacementPath}`); } diff --git a/tests/lib/rules/no-get.js b/tests/lib/rules/no-get.js index 09c588d6da..42285678da 100644 --- a/tests/lib/rules/no-get.js +++ b/tests/lib/rules/no-get.js @@ -177,6 +177,7 @@ ruleTester.run('no-get', rule, { // Optional chaining: 'this.foo?.bar', + 'this.foo?.[0]?.bar', ], invalid: [ // ************************** @@ -403,6 +404,29 @@ ruleTester.run('no-get', rule, { }, ], }, + { + // Handle array element access with optional chaining. + code: "this.get('foo1.0.bar1bar.1')", + options: [{ useOptionalChaining: true }], + output: 'this.foo1?.[0]?.bar1bar?.[1]', + errors: [ + { + message: ERROR_MESSAGE_GET, + type: 'CallExpression', + }, + ], + }, + { + // Handle array element access (left side of an assignment). + code: "this.get('foo.0.bar')[123] = 'hello world';", + output: "this.foo[0].bar[123] = 'hello world';", + errors: [ + { + message: ERROR_MESSAGE_GET, + type: 'CallExpression', + }, + ], + }, { // We can safely autofix nested paths in the left side of an assignment, // even when the `useOptionalChaining` option is off.