nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: ember-cli/eslint-plugin-ember
Pull request #1001 (2020-11-06 19:52:06)

Fix issues with `no-get` rule autofix with array access in nested path


Patch:
diff --git a/lib/rules/no-get.js b/lib/rules/no-get.js
index 492a5dbd..043beaee 100644
--- a/lib/rules/no-get.js
+++ b/lib/rules/no-get.js
@@ -65,7 +65,8 @@ function fixGet({
   // Replace any array element access (foo.1 => foo[1] or foo?.[1]).
   replacementPath = replacementPath
     .replace(/\.(\d+)/g, isInLeftSideOfAssignmentExpression ? '[$1]' : '.[$1]') // Usages in middle of path.
-    .replace(/^(\d+)\?\./, isInLeftSideOfAssignmentExpression ? '[$1]' : '[$1]?.'); // Usage at beginning of path.
+    .replace(/^(\d+)\??\./, isInLeftSideOfAssignmentExpression ? '[$1].' : '[$1]?.') // Usage at beginning of path.
+    .replace(/^(\d+)$/, '[$1]'); // Usage as entire string.
 
   // Add parenthesis around the object text in case of something like this: get(foo || {}, 'bar')
   const objectTextSafe = isValidJSPath(objectText) ? objectText : `(${objectText})`;


Test patch:
diff --git a/tests/lib/rules/no-get.js b/tests/lib/rules/no-get.js
index eb25e4c3..27034164 100644
--- a/tests/lib/rules/no-get.js
+++ b/tests/lib/rules/no-get.js
@@ -425,10 +425,10 @@ ruleTester.run('no-get', rule, {
       ],
     },
     {
-      // Handle array element access with optional chaining.
-      code: "this.get('foo1.0.bar1bar.1')",
+      // Handle array element access with optional chaining (beginning/middle/end of string).
+      code: "this.get('0.foo1.1.2.bar1bar.3')",
       options: [{ useOptionalChaining: true }],
-      output: 'this.foo1?.[0]?.bar1bar?.[1]',
+      output: 'this[0]?.foo1?.[1]?.[2]?.bar1bar?.[3]',
       errors: [
         {
           message: ERROR_MESSAGE_GET,
@@ -437,10 +437,10 @@ ruleTester.run('no-get', rule, {
       ],
     },
     {
-      // Handle array element access at beginning of string, with optional chaining.
-      code: "this.get('0.foo')",
+      // Handle array element access as entire string.
+      code: "this.get('0')",
       options: [{ useOptionalChaining: true }],
-      output: 'this[0]?.foo',
+      output: 'this[0]',
       errors: [
         {
           message: ERROR_MESSAGE_GET,
@@ -449,9 +449,20 @@ ruleTester.run('no-get', rule, {
       ],
     },
     {
-      // 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';",
+      // Handle array element access (left side of an assignment, beginning/middle/end of string).
+      code: "this.get('0.foo.1.bar.2')[123] = 'hello world';",
+      output: "this[0].foo[1].bar[2][123] = 'hello world';",
+      errors: [
+        {
+          message: ERROR_MESSAGE_GET,
+          type: 'CallExpression',
+        },
+      ],
+    },
+    {
+      // Handle array element access (left side of an assignment, entire string).
+      code: "this.get('0')[123] = 'hello world';",
+      output: "this[0][123] = 'hello world';",
       errors: [
         {
           message: ERROR_MESSAGE_GET,
Repository: ember-cli/eslint-plugin-ember
Pull request #1030 (2020-12-04 17:27:48)

Allow using string functions directly from Ember in `no-string-prototype-extensions` rule
Using string functions directly from Ember is allowed:

```js
import Ember from 'ember';
Ember.String.htmlSafe('foo');
```

This is the old module import style that some older Ember applications might still be using.


Patch:
diff --git a/lib/rules/no-string-prototype-extensions.js b/lib/rules/no-string-prototype-extensions.js
index 0dbdc2cb..dae2dba9 100644
--- a/lib/rules/no-string-prototype-extensions.js
+++ b/lib/rules/no-string-prototype-extensions.js
@@ -1,5 +1,7 @@
 'use strict';
 
+const { getImportIdentifier } = require('../utils/import');
+
 const ERROR_MESSAGE = 'Do not using `String` prototype extension methods.';
 
 const EXTENSION_METHODS = new Set([
@@ -31,6 +33,8 @@ module.exports = {
   ERROR_MESSAGE,
 
   create(context) {
+    let importedEmberName;
+
     return {
       CallExpression(node) {
         const { callee } = node;
@@ -46,10 +50,27 @@ module.exports = {
           return;
         }
 
+        if (
+          object.type === 'MemberExpression' &&
+          object.object.type === 'Identifier' &&
+          object.object.name === importedEmberName &&
+          object.property.type === 'Identifier' &&
+          object.property.name === 'String'
+        ) {
+          // Using functions directly from "Ember.String..." is allowed.
+          return;
+        }
+
         if (EXTENSION_METHODS.has(property.name)) {
           context.report({ node: property, message: ERROR_MESSAGE });
         }
       },
+
+      ImportDeclaration(node) {
+        if (node.source.value === 'ember') {
+          importedEmberName = importedEmberName || getImportIdentifier(node, 'ember');
+        }
+      },
     };
   },
 };


Test patch:
diff --git a/tests/lib/rules/no-string-prototype-extensions.js b/tests/lib/rules/no-string-prototype-extensions.js
index 801eae3c..e30912fc 100644
--- a/tests/lib/rules/no-string-prototype-extensions.js
+++ b/tests/lib/rules/no-string-prototype-extensions.js
@@ -12,13 +12,17 @@ const ruleTester = new RuleTester({
 
 ruleTester.run('no-string-prototype-extensions', rule, {
   valid: [
-    "dasherize('myString')",
-    'capitalize(someString)',
-    "htmlSafe('<b>foo</b>')",
+    "import { dasherize } from '@ember/string'; dasherize('myString')",
+    "import { capitalize } from '@ember/string'; capitalize(someString)",
+    "import { htmlSafe } from '@ember/template'; htmlSafe('<b>foo</b>')",
     "someString['foo']()",
     'something.foo()',
     'dasherize.foo()',
     'this.dasherize()',
+
+    // Still allowed to use directly from Ember:
+    "import Ember from 'ember'; Ember.String.htmlSafe('foo');",
+    "import Ember from 'ember'; Ember.String.dasherize('foo');",
   ],
 
   invalid: [
Repository: ember-cli/eslint-plugin-ember
Pull request #1168 (2021-04-21 23:07:29)

Avoid some false positives with jQuery usage when recognizing extended objects


Patch:
diff --git a/lib/utils/ember.js b/lib/utils/ember.js
index 8f140ac0..2276a708 100644
--- a/lib/utils/ember.js
+++ b/lib/utils/ember.js
@@ -188,10 +188,20 @@ function isMirageConfig(fileName) {
   return path.normalize(fileName).endsWith(path.join('mirage', 'config.js'));
 }
 
+// jQuery has an `extend` function and we want to avoid mistaking it for an extended object.
+// TODO: ideally, this would check the actual name that jQuery is imported under, but there's a lot of plumbing needed for that.
+const COMMON_JQUERY_NAMES = new Set(['$', 'jQuery']);
+
 function isExtendObject(node) {
+  // Check for:
+  // * foo.extend();
+  // * foo['extend']();
   return (
-    node.callee.property &&
-    (node.callee.property.name === 'extend' || node.callee.property.value === 'extend')
+    node.type === 'CallExpression' &&
+    node.callee.type === 'MemberExpression' &&
+    ((node.callee.property.type === 'Identifier' && node.callee.property.name === 'extend') ||
+      (node.callee.property.type === 'Literal' && node.callee.property.value === 'extend')) &&
+    !(node.callee.object.type === 'Identifier' && COMMON_JQUERY_NAMES.has(node.callee.object.name))
   );
 }
 


Test patch:
diff --git a/tests/lib/utils/ember-test.js b/tests/lib/utils/ember-test.js
index a389049e..4f6e679a 100644
--- a/tests/lib/utils/ember-test.js
+++ b/tests/lib/utils/ember-test.js
@@ -556,6 +556,48 @@ describe('isEmberService', () => {
   });
 });
 
+describe('isExtendObject', () => {
+  it('should detect using extend function name', () => {
+    const node = parse('foo.extend()');
+    expect(emberUtils.isExtendObject(node)).toBeTruthy();
+  });
+
+  it('should detect using extend string name', () => {
+    const node = parse('foo["extend"]()');
+    expect(emberUtils.isExtendObject(node)).toBeTruthy();
+  });
+
+  it('should detect using nested object', () => {
+    const node = parse('foo.bar.extend()');
+    expect(emberUtils.isExtendObject(node)).toBeTruthy();
+  });
+
+  it('should not detect a potential jQuery usage with `$`', () => {
+    const node = parse('$.extend()');
+    expect(emberUtils.isExtendObject(node)).toBeFalsy();
+  });
+
+  it('should not detect a potential jQuery usage with `jQuery`', () => {
+    const node = parse('jQuery.extend()');
+    expect(emberUtils.isExtendObject(node)).toBeFalsy();
+  });
+
+  it('should not detect with non-extend name', () => {
+    const node = parse('foo.notExtend()');
+    expect(emberUtils.isExtendObject(node)).toBeFalsy();
+  });
+
+  it('should not detect with no object', () => {
+    const node = parse('extend()');
+    expect(emberUtils.isExtendObject(node)).toBeFalsy();
+  });
+
+  it('should not detect with wrong function', () => {
+    const node = parse('extend.foo()');
+    expect(emberUtils.isExtendObject(node)).toBeFalsy();
+  });
+});
+
 describe('isEmberArrayProxy', () => {
   it('should detect using old module style', () => {
     const context = new FauxContext('Ember.ArrayProxy.extend()');
Repository: ember-cli/eslint-plugin-ember
Pull request #1210 (2021-05-29 18:29:40)

Avoid some false positives with lodash usage when recognizing extended Ember objects
Follow-up to #1168.

Fixes this report: https://github.com/ember-cli/eslint-plugin-ember/issues/601#issuecomment-846266584

CC: @ballPointPenguin


Patch:
diff --git a/lib/utils/ember.js b/lib/utils/ember.js
index 503e9a5f..ea469d7c 100644
--- a/lib/utils/ember.js
+++ b/lib/utils/ember.js
@@ -183,9 +183,11 @@ function isMirageConfig(fileName) {
   return path.normalize(fileName).endsWith(path.join('mirage', 'config.js'));
 }
 
-// jQuery has an `extend` function and we want to avoid mistaking it for an extended object.
-// TODO: ideally, this would check the actual name that jQuery is imported under, but there's a lot of plumbing needed for that.
-const COMMON_JQUERY_NAMES = new Set(['$', 'jQuery']);
+// Some third-party libraries have an `extend` function and we want to avoid mistaking this for an extended Ember object.
+// TODO: ideally, this would check the actual name that these libraries are imported under, but there's a lot of plumbing needed for that.
+const COMMON_JQUERY_NAMES = ['$', 'jQuery']; // https://api.jquery.com/jquery.extend/
+const COMMON_LODASH_NAMES = ['_', 'lodash']; // https://lodash.com/docs/4.17.15#assignIn
+const THIRD_PARTY_LIBRARIES_WITH_EXTEND = new Set([...COMMON_JQUERY_NAMES, ...COMMON_LODASH_NAMES]);
 
 function isExtendObject(node) {
   // Check for:
@@ -196,7 +198,10 @@ function isExtendObject(node) {
     node.callee.type === 'MemberExpression' &&
     ((node.callee.property.type === 'Identifier' && node.callee.property.name === 'extend') ||
       (node.callee.property.type === 'Literal' && node.callee.property.value === 'extend')) &&
-    !(node.callee.object.type === 'Identifier' && COMMON_JQUERY_NAMES.has(node.callee.object.name))
+    !(
+      node.callee.object.type === 'Identifier' &&
+      THIRD_PARTY_LIBRARIES_WITH_EXTEND.has(node.callee.object.name)
+    )
   );
 }
 


Test patch:
diff --git a/tests/lib/utils/ember-test.js b/tests/lib/utils/ember-test.js
index edab2dc5..d633c5e4 100644
--- a/tests/lib/utils/ember-test.js
+++ b/tests/lib/utils/ember-test.js
@@ -582,6 +582,11 @@ describe('isExtendObject', () => {
     expect(emberUtils.isExtendObject(node)).toBeFalsy();
   });
 
+  it('should not detect a potential lodash usage', () => {
+    expect(emberUtils.isExtendObject(parse('_.extend()'))).toBeFalsy();
+    expect(emberUtils.isExtendObject(parse('lodash.extend()'))).toBeFalsy();
+  });
+
   it('should not detect with non-extend name', () => {
     const node = parse('foo.notExtend()');
     expect(emberUtils.isExtendObject(node)).toBeFalsy();
Repository: ember-cli/eslint-plugin-ember
Pull request #1286 (2021-08-24 01:33:32)

Avoid unnecessary optional chaining in autofix for `no-get` rule when using `useOptionalChaining` option
This maintains the behavior more closely when a nested chain contains a nullish value.

```
  // when foo or bar is nullish:
  this.get('foo.bar').baz // will error with "baz of undefined"
  this.foo?.bar?.baz      // (previous behavior) evaluates to `undefined`
  this.foo.bar.baz        // (updated behavior)  errors with either "bar of undefined" or "baz of undefined"
```




Patch:
diff --git a/lib/rules/no-get.js b/lib/rules/no-get.js
index 23278a3f..cb432df8 100644
--- a/lib/rules/no-get.js
+++ b/lib/rules/no-get.js
@@ -59,8 +59,12 @@ function fixGet({
     return null;
   }
 
+  const getResultIsChained = node.parent.type === 'MemberExpression' && node.parent.object === node;
+
+  // If the result of get is chained, we can safely autofix nests paths without using optional chaining.
   // In the left side of an assignment, we can safely autofix nested paths without using optional chaining.
-  let replacementPath = isInLeftSideOfAssignmentExpression ? path : path.replace(/\./g, '?.');
+  let replacementPath =
+    getResultIsChained || isInLeftSideOfAssignmentExpression ? path : path.replace(/\./g, '?.');
 
   // Replace any array element access (foo.1 => foo[1] or foo?.[1]).
   replacementPath = replacementPath


Test patch:
diff --git a/tests/lib/rules/no-get.js b/tests/lib/rules/no-get.js
index e418f26c..cb8b39fb 100644
--- a/tests/lib/rules/no-get.js
+++ b/tests/lib/rules/no-get.js
@@ -209,6 +209,24 @@ ruleTester.run('no-get', rule, {
       options: [{ catchUnsafeObjects: true }],
       errors: [{ message: ERROR_MESSAGE_GET, type: 'CallExpression' }],
     },
+    {
+      code: "foo1.foo2.get('bar').baz;",
+      output: 'foo1.foo2.bar.baz;',
+      options: [{ catchUnsafeObjects: true, useOptionalChaining: true }],
+      errors: [{ message: ERROR_MESSAGE_GET, type: 'CallExpression' }],
+    },
+    {
+      code: "foo1.foo2.get('bar.bar').baz;",
+      output: null,
+      options: [{ catchUnsafeObjects: true }],
+      errors: [{ message: ERROR_MESSAGE_GET, type: 'CallExpression' }],
+    },
+    {
+      code: "foo1.foo2.get('bar.bar').baz;",
+      output: 'foo1.foo2.bar.bar.baz;',
+      options: [{ catchUnsafeObjects: true, useOptionalChaining: true }],
+      errors: [{ message: ERROR_MESSAGE_GET, type: 'CallExpression' }],
+    },
     {
       code: `
       import { get } from '@ember/object';
@@ -372,6 +390,17 @@ ruleTester.run('no-get', rule, {
         },
       ],
     },
+    {
+      code: "this.get('foo.bar').baz;",
+      output: 'this.foo.bar.baz;',
+      options: [{ useOptionalChaining: true }],
+      errors: [
+        {
+          message: ERROR_MESSAGE_GET,
+          type: 'CallExpression',
+        },
+      ],
+    },
     {
       code: "this.get('very.long.path');",
       output: 'this.very?.long?.path;',