diff --git a/.github/workflows/update-snapshots.yml b/.github/workflows/update-snapshots.yml index bfcb3c3e2e..69d4835859 100644 --- a/.github/workflows/update-snapshots.yml +++ b/.github/workflows/update-snapshots.yml @@ -19,7 +19,7 @@ jobs: - run: npm run lint - run: rm -rf test/snapshots # Force update snapshots, https://github.com/avajs/ava/discussions/2754 - - run: npx c8 ava --update-snapshots + - run: npx ava --update-snapshots env: AVA_FORCE_CI: not-ci - uses: autofix-ci/action@v1 diff --git a/package.json b/package.json index c31e349088..c041fbeee8 100644 --- a/package.json +++ b/package.json @@ -80,8 +80,8 @@ "@babel/eslint-parser": "^7.28.5", "@eslint/eslintrc": "^3.3.1", "@lubien/fixture-beta-package": "^1.0.0-beta.1", - "@typescript-eslint/parser": "^8.46.2", - "@typescript-eslint/types": "^8.46.2", + "@typescript-eslint/parser": "^8.48.0", + "@typescript-eslint/types": "^8.48.0", "ava": "^6.4.1", "c8": "^10.1.3", "enquirer": "^2.4.1", diff --git a/rules/prefer-node-protocol.js b/rules/prefer-node-protocol.js index d373c4070c..8b96b384f4 100644 --- a/rules/prefer-node-protocol.js +++ b/rules/prefer-node-protocol.js @@ -21,6 +21,7 @@ const create = context => { node.parent.type === 'ImportDeclaration' || node.parent.type === 'ExportNamedDeclaration' || node.parent.type === 'ImportExpression' + || node.parent.type === 'TSImportType' ) && node.parent.source === node ) @@ -37,12 +38,6 @@ const create = context => { ) && node.parent.arguments[0] === node ) - || ( - node.parent.type === 'TSLiteralType' - && node.parent.literal === node - && node.parent.parent.type === 'TSImportType' - && node.parent.parent.argument === node.parent - ) )) { return; } diff --git a/rules/prefer-set-has.js b/rules/prefer-set-has.js index 59f6533925..5825ba352b 100644 --- a/rules/prefer-set-has.js +++ b/rules/prefer-set-has.js @@ -9,8 +9,13 @@ const messages = { [MESSAGE_ID_SUGGESTION]: 'Switch `{{name}}` to `Set`.', }; -const arrayMethodsReturnsArray = [ - 'concat', +/* +Some of these methods can be `Iterator`. + +Since `Iterator` don't have an `includes()` method, we are safe to assume they are array. Except `concat` and `slice` which can be a string: https://github.com/sindresorhus/eslint-plugin-unicorn/issues/2216 +*/ +const methodsReturnsArray = [ + // `Array` 'copyWithin', 'fill', 'filter', @@ -18,13 +23,22 @@ const arrayMethodsReturnsArray = [ 'flatMap', 'map', 'reverse', - 'slice', 'sort', 'splice', 'toReversed', 'toSorted', 'toSpliced', 'with', + + // `Array` or `String` (unsafe) + 'slice', + 'concat', + + // `String` + 'split', + + // `Iterator` + 'toArray', ]; const isIncludesCall = node => @@ -95,9 +109,9 @@ const create = context => { optionalCall: false, optionalMember: false, }) - // Array methods that return an array + // Methods that return an array || isMethodCall(parent.init, { - methods: arrayMethodsReturnsArray, + methods: methodsReturnsArray, optionalCall: false, optionalMember: false, }) diff --git a/rules/prefer-string-raw.js b/rules/prefer-string-raw.js index b200ff4ab4..3e9acabf12 100644 --- a/rules/prefer-string-raw.js +++ b/rules/prefer-string-raw.js @@ -67,6 +67,8 @@ function isStringRawRestricted(node) { || (type === 'TSExternalModuleReference' && parent.expression === node) // (TypeScript) Literal type || (type === 'TSLiteralType' && parent.literal === node) + // (TypeScript) Import type + || (type === 'TSImportType' && parent.source === node) ); } diff --git a/test/prefer-set-has.js b/test/prefer-set-has.js index b383e49805..14e2dcd29b 100644 --- a/test/prefer-set-has.js +++ b/test/prefer-set-has.js @@ -19,6 +19,8 @@ const methodsReturnsArray = [ 'toSorted', 'toSpliced', 'with', + 'toArray', + 'split', ]; test.snapshot({ diff --git a/test/prefer-string-raw.js b/test/prefer-string-raw.js index c60274c367..0e3ceec39b 100644 --- a/test/prefer-string-raw.js +++ b/test/prefer-string-raw.js @@ -139,6 +139,8 @@ test.snapshot({ String.raw`import type T = require('${TEST_STRING}');`, // (TypeScript) Literal type String.raw`type T = '${TEST_STRING}';`, + // (TypeScript) Import type + String.raw`type T = import('${TEST_STRING}');`, ...keyTestsComputedIsInvalid, ...keyTestsComputedIsValid.flatMap(code => [code, toComputed(code)]), `expect(foo).toMatchInlineSnapshot('${TEST_STRING}')`, diff --git a/test/snapshots/prefer-set-has.js.md b/test/snapshots/prefer-set-has.js.md index 89f67e320a..b96556f8dd 100644 --- a/test/snapshots/prefer-set-has.js.md +++ b/test/snapshots/prefer-set-has.js.md @@ -1346,7 +1346,63 @@ Generated by [AVA](https://avajs.dev). 4 | }␊ ` -## invalid(41): const foo = _([1,2,3]); const bar = foo.map(value => value); function unicorn() { return bar.includes(1); } +## invalid(41): const foo = bar.toArray(); function unicorn() { return foo.includes(1); } + +> Input + + `␊ + 1 | const foo = bar.toArray();␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + Message:␊ + > 1 | const foo = bar.toArray();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ␊ + Output:␊ + 1 | const foo = new Set(bar.toArray());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +## invalid(42): const foo = bar.split(); function unicorn() { return foo.includes(1); } + +> Input + + `␊ + 1 | const foo = bar.split();␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + Message:␊ + > 1 | const foo = bar.split();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ␊ + Output:␊ + 1 | const foo = new Set(bar.split());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +## invalid(43): const foo = _([1,2,3]); const bar = foo.map(value => value); function unicorn() { return bar.includes(1); } > Input diff --git a/test/snapshots/prefer-set-has.js.snap b/test/snapshots/prefer-set-has.js.snap index a64ffa1494..59b6e11901 100644 Binary files a/test/snapshots/prefer-set-has.js.snap and b/test/snapshots/prefer-set-has.js.snap differ