Repository: ember-cli/eslint-plugin-ember
Pull request #1687 (2022-11-30 20:19:07)

Don't lose optional chaining with `objectAt` in autofix for `no-array-prototype-extensions` rule
### Summary
Add optional chaining support to `objectAt` auto-fixer.

### Detail
Right now the `objectAt` auto-fixer in no-array-prototype-extensions will remove the optional chaining operator(?.). So this PR will use `callExpressionNode.callee.optional` to check the optional chaining use case and keep the optional chaining operator.

For example, the following template
const response = this.demoResponses?.objectAt(questionIndex);

Before:
const response = this.demoResponses[questionIndex];

After:
const response = this.demoResponses?.[questionIndex];

### Testing Done
Add two new test cases to check the optional chaining use case.
All test cases passed.

bmish: Do you think this is an issue with any of the other functions in the autofix?
bmish: Feel free to use fix the issues with the other functions in separate PRs or in the same PR, up to your preference. For the next PR you could try to address multiple functions if you want. Looks like this PR is almost finished except you need to fix lint (and I recommend enabling trim trailing whitespace in your editor).
52052100: > Feel free to use fix the issues with the other functions in separate PRs or in the same PR, up to your preference. For the next PR you could try to address multiple functions if you want. Looks like this PR is almost finished except you need to fix lint (and I recommend enabling trim trailing whitespace in your editor).

Sure, no problem! I will try to fix other functions in separate PRs to make sure don't break the function. Thanks for the suggestion! Just updated the code format and push.

Patch:
diff --git a/lib/rules/no-array-prototype-extensions.js b/lib/rules/no-array-prototype-extensions.js
index 4bacfb38..d3aa8799 100644
--- a/lib/rules/no-array-prototype-extensions.js
+++ b/lib/rules/no-array-prototype-extensions.js
@@ -318,7 +318,9 @@ function applyFix(callExpressionNode, fixer, context, options = {}) {
         return [
           fixer.insertTextBefore(
             callExpressionNode,
-            `${sourceCode.getText(calleeObj)}[${sourceCode.getText(callArgs[0])}]`
+            `${sourceCode.getText(calleeObj)}${
+              callExpressionNode.callee.optional ? '?.' : ''
+            }[${sourceCode.getText(callArgs[0])}]`
           ),
           fixer.remove(callExpressionNode),
         ];


Test patch:
diff --git a/tests/lib/rules/no-array-prototype-extensions.js b/tests/lib/rules/no-array-prototype-extensions.js
index 26db42ec..899732e2 100644
--- a/tests/lib/rules/no-array-prototype-extensions.js
+++ b/tests/lib/rules/no-array-prototype-extensions.js
@@ -696,12 +696,23 @@ import { get as g } from 'dummy';
       output: 'something[1]',
       errors: [{ messageId: 'main', type: 'CallExpression' }],
     },
+    {
+      code: 'something?.objectAt(1)',
+      output: 'something?.[1]',
+      errors: [{ messageId: 'main', type: 'CallExpression' }],
+    },
     {
       // Function call in chain
       code: 'something.somethingElse.objectAt(1)',
       output: 'something.somethingElse[1]',
       errors: [{ messageId: 'main', type: 'CallExpression' }],
     },
+    {
+      // Function call in optional chaining
+      code: 'something.somethingElse?.objectAt(1)',
+      output: 'something.somethingElse?.[1]',
+      errors: [{ messageId: 'main', type: 'CallExpression' }],
+    },
     {
       // When unexpected number of arguments are passed, auto-fixer will not run
       code: 'something.objectsAt()',