diff --git a/package.json b/package.json index 95e1a16920..d1357c951e 100644 --- a/package.json +++ b/package.json @@ -109,6 +109,9 @@ ] }, "xo": { + "extends": [ + "plugin:internal-rules/all" + ], "ignores": [ ".cache-eslint-remote-tester", "eslint-remote-tester-results", @@ -160,14 +163,6 @@ "eslint-plugin/require-meta-has-suggestions": "off", "eslint-plugin/require-meta-schema": "off" } - }, - { - "files": [ - "rules/**/*.js" - ], - "extends": [ - "plugin:internal-rules/all" - ] } ] }, diff --git a/rules/no-useless-spread.js b/rules/no-useless-spread.js index dd976c0a70..f75269ffaf 100644 --- a/rules/no-useless-spread.js +++ b/rules/no-useless-spread.js @@ -148,11 +148,11 @@ function * unwrapSingleArraySpread(fixer, arrayExpression, sourceCode) { ] = sourceCode.getLastTokens(arrayExpression, 2); // `[...value]` - // ^ + // ^ yield fixer.remove(closingBracketToken); // `[...value,]` - // ^ + // ^ if (isCommaToken(commaToken)) { yield fixer.remove(commaToken); } diff --git a/scripts/internal-rules/fix-snapshot-test.js b/scripts/internal-rules/fix-snapshot-test.js new file mode 100644 index 0000000000..6ee0ab006e --- /dev/null +++ b/scripts/internal-rules/fix-snapshot-test.js @@ -0,0 +1,130 @@ +'use strict'; +const assert = require('node:assert'); +const { + isCommaToken, +} = require('@eslint-community/eslint-utils'); +const {methodCallSelector} = require('../../rules/selectors/index.js'); + +const MESSAGE_ID_DISALLOWED_PROPERTY = 'disallow-property'; +const MESSAGE_ID_NO_SINGLE_CODE_OBJECT = 'use-string'; +const MESSAGE_ID_REMOVE_FIX_MARK_COMMENT = 'remove-fix-mark'; +const messages = { + [MESSAGE_ID_DISALLOWED_PROPERTY]: '"{{name}}" not allowed.{{autoFixEnableTip}}', + [MESSAGE_ID_NO_SINGLE_CODE_OBJECT]: 'Use string instead of object with "code".', + [MESSAGE_ID_REMOVE_FIX_MARK_COMMENT]: 'This comment should be removed.', +}; + +// Top-level `test.snapshot({invalid: []})` +const selector = [ + 'Program > ExpressionStatement.body > .expression', + // `test.snapshot()` + methodCallSelector({ + argumentsLength: 1, + object: 'test', + method: 'snapshot', + }), + ' > ObjectExpression.arguments:first-child', + /* + ``` + test.snapshot({ + invalid: [], <- Property + }) + ``` + */ + ' > Property.properties', + '[computed!=true]', + '[method!=true]', + '[shorthand!=true]', + '[kind="init"]', + '[key.type="Identifier"]', + '[key.name="invalid"]', + + ' > ArrayExpression.value', + ' > ObjectExpression.elements', + ' > Property.properties[computed!=true][key.type="Identifier"]', +].join(''); + +function * removeObjectProperty(node, fixer, sourceCode) { + yield fixer.remove(node); + const nextToken = sourceCode.getTokenAfter(node); + if (isCommaToken(nextToken)) { + yield fixer.remove(nextToken); + } +} + +// The fix deletes lots of code, disabled auto-fix by default, unless `/* fix */ test.snapshot()` pattern is used. +function hasFixMarkComment(propertyNode, sourceCode) { + const snapshotTestCall = propertyNode.parent.parent.parent.parent.parent; + assert.ok(snapshotTestCall.type === 'CallExpression'); + const comment = sourceCode.getTokenBefore(snapshotTestCall, {includeComments: true}); + + if ( + (comment?.type === 'Block' || comment?.type === 'Line') + && comment.value.trim().toLowerCase() === 'fix' + && ( + comment.loc.start.line === snapshotTestCall.loc.start.line + || comment.loc.start.line === snapshotTestCall.loc.start.line - 1 + ) + ) { + return true; + } +} + +module.exports = { + create(context) { + const sourceCode = context.getSourceCode(); + + return { + [selector](propertyNode) { + const {key} = propertyNode; + + switch (key.name) { + case 'errors': + case 'output': { + const canFix = sourceCode.getCommentsInside(propertyNode).length === 0; + const hasFixMark = hasFixMarkComment(propertyNode, sourceCode); + + context.report({ + node: key, + messageId: MESSAGE_ID_DISALLOWED_PROPERTY, + data: { + name: key.name, + autoFixEnableTip: !hasFixMark && canFix + ? ' Put /* fix */ before `test.snapshot()` to enable auto-fix.' + : '', + }, + fix: hasFixMark && canFix + ? fixer => removeObjectProperty(propertyNode, fixer, sourceCode) + : undefined + , + }); + break; + } + + case 'code': { + const testCase = propertyNode.parent; + if (testCase.properties.length === 1) { + const commentsCount = sourceCode.getCommentsInside(testCase).length + - sourceCode.getCommentsInside(propertyNode).length; + context.report({ + node: testCase, + messageId: MESSAGE_ID_NO_SINGLE_CODE_OBJECT, + fix: commentsCount === 0 + ? fixer => fixer.replaceText(testCase, sourceCode.getText(propertyNode.value)) + : undefined, + }); + } + + break; + } + + // No default + } + }, + }; + }, + meta: { + fixable: 'code', + messages, + }, +}; diff --git a/scripts/internal-rules/index.js b/scripts/internal-rules/index.js index ab042b0995..e53776bbe8 100644 --- a/scripts/internal-rules/index.js +++ b/scripts/internal-rules/index.js @@ -1,18 +1,47 @@ 'use strict'; +const path = require('node:path'); + const pluginName = 'internal-rules'; +const TEST_DIRECTORIES = [ + path.join(__dirname, '../../test'), +]; +const RULES_DIRECTORIES = [ + path.join(__dirname, '../../rules'), +]; const rules = [ - 'prefer-negative-boolean-attribute', - 'prefer-disallow-over-forbid', + {id: 'fix-snapshot-test', directories: TEST_DIRECTORIES}, + {id: 'prefer-disallow-over-forbid', directories: RULES_DIRECTORIES}, + {id: 'prefer-negative-boolean-attribute', directories: RULES_DIRECTORIES}, ]; +const isFileInsideDirectory = (filename, directory) => filename.startsWith(directory + path.sep); + module.exports = { - rules: Object.fromEntries(rules.map(id => [id, require(`./${id}.js`)])), + rules: Object.fromEntries( + rules.map(({id, directories}) => { + const rule = require(`./${id}.js`); + return [ + id, + { + ...rule, + create(context) { + const filename = context.getPhysicalFilename(); + if (directories.every(directory => !isFileInsideDirectory(filename, directory))) { + return {}; + } + + return rule.create(context); + }, + }, + ]; + }), + ), configs: { all: { plugins: [pluginName], - rules: Object.fromEntries(rules.map(id => [`${pluginName}/${id}`, 'error'])), + rules: Object.fromEntries(rules.map(({id}) => [`${pluginName}/${id}`, 'error'])), }, }, }; diff --git a/test/prefer-set-has.mjs b/test/prefer-set-has.mjs index 9fc18c0362..4dd341e6c2 100644 --- a/test/prefer-set-has.mjs +++ b/test/prefer-set-has.mjs @@ -1,17 +1,8 @@ import outdent from 'outdent'; -import {getTester} from './utils/test.mjs'; +import {getTester, parsers} from './utils/test.mjs'; const {test} = getTester(import.meta); -const createError = name => [ - { - messageId: 'error', - data: { - name, - }, - }, -]; - const methodsReturnsArray = [ 'concat', 'copyWithin', @@ -26,7 +17,7 @@ const methodsReturnsArray = [ 'splice', ]; -test({ +test.snapshot({ valid: [ outdent` const foo = new Set([1, 2, 3]); @@ -387,524 +378,245 @@ test({ `, ], invalid: [ - { - code: outdent` - const foo = [1, 2, 3]; - function unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + function unicorn() { + return foo.includes(1); + } + `, // Called multiple times - { - code: outdent` - const foo = [1, 2, 3]; - const isExists = foo.includes(1); - const isExists2 = foo.includes(2); - `, - output: outdent` - const foo = new Set([1, 2, 3]); - const isExists = foo.has(1); - const isExists2 = foo.has(2); - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + const isExists = foo.includes(1); + const isExists2 = foo.includes(2); + `, // `ForOfStatement` - { - code: outdent` + outdent` + const foo = [1, 2, 3]; + for (const a of b) { + foo.includes(1); + } + `, + outdent` + async function unicorn() { const foo = [1, 2, 3]; - for (const a of b) { + for await (const a of b) { foo.includes(1); } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - for (const a of b) { - foo.has(1); - } - `, - errors: createError('foo'), - }, - { - code: outdent` - async function unicorn() { - const foo = [1, 2, 3]; - for await (const a of b) { - foo.includes(1); - } - } - `, - output: outdent` - async function unicorn() { - const foo = new Set([1, 2, 3]); - for await (const a of b) { - foo.has(1); - } - } - `, - errors: createError('foo'), - }, + } + `, // `ForStatement` - { - code: outdent` - const foo = [1, 2, 3]; - for (let i = 0; i < n; i++) { - foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - for (let i = 0; i < n; i++) { - foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + for (let i = 0; i < n; i++) { + foo.includes(1); + } + `, // `ForInStatement` - { - code: outdent` - const foo = [1, 2, 3]; - for (let a in b) { - foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - for (let a in b) { - foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + for (let a in b) { + foo.includes(1); + } + `, // `WhileStatement` - { - code: outdent` - const foo = [1, 2, 3]; - while (a) { - foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - while (a) { - foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + while (a) { + foo.includes(1); + } + `, // `DoWhileStatement` - { - code: outdent` - const foo = [1, 2, 3]; - do { - foo.includes(1); - } while (a) - `, - output: outdent` - const foo = new Set([1, 2, 3]); - do { - foo.has(1); - } while (a) - `, - errors: createError('foo'), - }, - { - code: outdent` - const foo = [1, 2, 3]; - do { - // … - } while (foo.includes(1)) - `, - output: outdent` - const foo = new Set([1, 2, 3]); - do { - // … - } while (foo.has(1)) - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + do { + foo.includes(1); + } while (a) + `, + outdent` + const foo = [1, 2, 3]; + do { + // … + } while (foo.includes(1)) + `, // `function` https://github.com/estools/esquery/blob/master/esquery.js#L216 // `FunctionDeclaration` - { - code: outdent` - const foo = [1, 2, 3]; - function unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, - { - code: outdent` - const foo = [1, 2, 3]; - function * unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - function * unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, - { - code: outdent` - const foo = [1, 2, 3]; - async function unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - async function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, - { - code: outdent` - const foo = [1, 2, 3]; - async function * unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - async function * unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + function unicorn() { + return foo.includes(1); + } + `, + outdent` + const foo = [1, 2, 3]; + function * unicorn() { + return foo.includes(1); + } + `, + outdent` + const foo = [1, 2, 3]; + async function unicorn() { + return foo.includes(1); + } + `, + outdent` + const foo = [1, 2, 3]; + async function * unicorn() { + return foo.includes(1); + } + `, // `FunctionExpression` - { - code: outdent` - const foo = [1, 2, 3]; - const unicorn = function () { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - const unicorn = function () { - return foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + const unicorn = function () { + return foo.includes(1); + } + `, // `ArrowFunctionExpression` - { - code: outdent` - const foo = [1, 2, 3]; - const unicorn = () => foo.includes(1); - `, - output: outdent` - const foo = new Set([1, 2, 3]); - const unicorn = () => foo.has(1); - `, - errors: createError('foo'), - }, - - { - code: outdent` - const foo = [1, 2, 3]; - const a = { - b() { - return foo.includes(1); - } - }; - `, - output: outdent` - const foo = new Set([1, 2, 3]); - const a = { - b() { - return foo.has(1); - } - }; - `, - errors: createError('foo'), - }, + outdent` + const foo = [1, 2, 3]; + const unicorn = () => foo.includes(1); + `, - { - code: outdent` - const foo = [1, 2, 3]; - class A { - b() { - return foo.includes(1); - } - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - class A { - b() { - return foo.has(1); - } + outdent` + const foo = [1, 2, 3]; + const a = { + b() { + return foo.includes(1); } - `, - errors: createError('foo'), - }, + }; + `, - // SpreadElement - { - code: outdent` - const foo = [...bar]; - function unicorn() { + outdent` + const foo = [1, 2, 3]; + class A { + b() { return foo.includes(1); } - bar.pop(); - `, - output: outdent` - const foo = new Set([...bar]); - function unicorn() { - return foo.has(1); - } - bar.pop(); - `, - errors: createError('foo'), - }, - // Multiple references - { - code: outdent` - const foo = [1, 2, 3]; - function unicorn() { - const exists = foo.includes(1); - function isExists(find) { - return foo.includes(find); - } - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - function unicorn() { - const exists = foo.has(1); - function isExists(find) { - return foo.has(find); - } - } - `, - errors: createError('foo'), - }, - { - code: outdent` - function wrap() { - const foo = [1, 2, 3]; + } + `, - function unicorn() { - return foo.includes(1); - } + // SpreadElement + outdent` + const foo = [...bar]; + function unicorn() { + return foo.includes(1); + } + bar.pop(); + `, + // Multiple references + outdent` + const foo = [1, 2, 3]; + function unicorn() { + const exists = foo.includes(1); + function isExists(find) { + return foo.includes(find); } - - const bar = [4, 5, 6]; + } + `, + outdent` + function wrap() { + const foo = [1, 2, 3]; function unicorn() { - return bar.includes(1); - } - `, - output: outdent` - function wrap() { - const foo = new Set([1, 2, 3]); - - function unicorn() { - return foo.has(1); - } + return foo.includes(1); } + } - const bar = new Set([4, 5, 6]); + const bar = [4, 5, 6]; - function unicorn() { - return bar.has(1); - } - `, - errors: [ - ...createError('foo'), - ...createError('bar'), - ], - }, + function unicorn() { + return bar.includes(1); + } + `, // Different scope - { - code: outdent` - const foo = [1, 2, 3]; - function wrap() { - const exists = foo.includes(1); - const bar = [1, 2, 3]; - - function outer(find) { - const foo = [1, 2, 3]; - while (a) { - foo.includes(1); - } + outdent` + const foo = [1, 2, 3]; + function wrap() { + const exists = foo.includes(1); + const bar = [1, 2, 3]; - function inner(find) { - const bar = [1, 2, 3]; - while (a) { - const exists = bar.includes(1); - } - } + function outer(find) { + const foo = [1, 2, 3]; + while (a) { + foo.includes(1); } - } - `, - output: outdent` - const foo = new Set([1, 2, 3]); - function wrap() { - const exists = foo.has(1); - const bar = [1, 2, 3]; - - function outer(find) { - const foo = new Set([1, 2, 3]); - while (a) { - foo.has(1); - } - function inner(find) { - const bar = new Set([1, 2, 3]); - while (a) { - const exists = bar.has(1); - } + function inner(find) { + const bar = [1, 2, 3]; + while (a) { + const exists = bar.includes(1); } } } - `, - errors: [ - ...createError('foo'), - ...createError('foo'), - ...createError('bar'), - ], - }, + } + `, // `Array()` - { - code: outdent` - const foo = Array(1, 2); - function unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set(Array(1, 2)); - function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = Array(1, 2); + function unicorn() { + return foo.includes(1); + } + `, // `new Array()` - { - code: outdent` - const foo = new Array(1, 2); - function unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set(new Array(1, 2)); - function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = new Array(1, 2); + function unicorn() { + return foo.includes(1); + } + `, // `Array.from()` - { - code: outdent` - const foo = Array.from({length: 1}, (_, index) => index); - function unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set(Array.from({length: 1}, (_, index) => index)); - function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = Array.from({length: 1}, (_, index) => index); + function unicorn() { + return foo.includes(1); + } + `, // `Array.of()` - { - code: outdent` - const foo = Array.of(1, 2); - function unicorn() { - return foo.includes(1); - } - `, - output: outdent` - const foo = new Set(Array.of(1, 2)); - function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - }, + outdent` + const foo = Array.of(1, 2); + function unicorn() { + return foo.includes(1); + } + `, // Methods - ...methodsReturnsArray.map(method => ({ - code: outdent` + ...methodsReturnsArray.map(method => + outdent` const foo = bar.${method}(); function unicorn() { return foo.includes(1); } `, - output: outdent` - const foo = new Set(bar.${method}()); - function unicorn() { - return foo.has(1); - } - `, - errors: createError('foo'), - })), + ), // `lodash` // `bar` is not `array`, but code not broken // See https://github.com/sindresorhus/eslint-plugin-unicorn/pull/641 - { - code: outdent` - const foo = _([1,2,3]); - const bar = foo.map(value => value); - function unicorn() { - return bar.includes(1); - } - `, - output: outdent` - const foo = _([1,2,3]); - const bar = new Set(foo.map(value => value)); - function unicorn() { - return bar.has(1); - } - `, - errors: createError('bar'), - }, + outdent` + const foo = _([1,2,3]); + const bar = foo.map(value => value); + function unicorn() { + return bar.includes(1); + } + `, ], }); -test.babel({ +test.snapshot({ testerOptions: { + parser: parsers.babel, parserOptions: { babelOptions: { parserOpts: { @@ -937,7 +649,10 @@ test.babel({ ], }); -test.typescript({ +test.snapshot({ + testerOptions: { + parser: parsers.typescript, + }, valid: [ // https://github.com/TheThingsNetwork/lorawan-stack/blob/1dab30227e632ceade425e0c67d5f84316e830da/pkg/webui/console/containers/device-importer/index.js#L74 outdent` @@ -956,35 +671,14 @@ test.typescript({ `, ], invalid: [ - { - code: outdent` - const a: Array<'foo' | 'bar'> = ['foo', 'bar'] + outdent` + const a: Array<'foo' | 'bar'> = ['foo', 'bar'] - for (let i = 0; i < 3; i++) { - if (a.includes(someString)) { - console.log(123) - } + for (let i = 0; i < 3; i++) { + if (a.includes(someString)) { + console.log(123) } - `, - errors: [ - { - message: '`a` should be a `Set`, and use `a.has()` to check existence or non-existence.', - suggestions: [ - { - desc: 'Switch `a` to `Set`.', - output: outdent` - const a: Array<'foo' | 'bar'> = new Set(['foo', 'bar']) - - for (let i = 0; i < 3; i++) { - if (a.has(someString)) { - console.log(123) - } - } - `, - }, - ], - }, - ], - }, + } + `, ], }); diff --git a/test/snapshots/prefer-set-has.mjs.md b/test/snapshots/prefer-set-has.mjs.md new file mode 100644 index 0000000000..1a6e1f13ef --- /dev/null +++ b/test/snapshots/prefer-set-has.mjs.md @@ -0,0 +1,1127 @@ +# Snapshot report for `test/prefer-set-has.mjs` + +The actual snapshot is saved in `prefer-set-has.mjs.snap`. + +Generated by [AVA](https://avajs.dev). + +## Invalid #1 + 1 | const foo = [1, 2, 3]; + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #2 + 1 | const foo = [1, 2, 3]; + 2 | const isExists = foo.includes(1); + 3 | const isExists2 = foo.includes(2); + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | const isExists = foo.has(1);␊ + 3 | const isExists2 = foo.has(2);␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | const isExists = foo.includes(1);␊ + 3 | const isExists2 = foo.includes(2);␊ + ` + +## Invalid #3 + 1 | const foo = [1, 2, 3]; + 2 | for (const a of b) { + 3 | foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | for (const a of b) {␊ + 3 | foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | for (const a of b) {␊ + 3 | foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #4 + 1 | async function unicorn() { + 2 | const foo = [1, 2, 3]; + 3 | for await (const a of b) { + 4 | foo.includes(1); + 5 | } + 6 | } + +> Output + + `␊ + 1 | async function unicorn() {␊ + 2 | const foo = new Set([1, 2, 3]);␊ + 3 | for await (const a of b) {␊ + 4 | foo.has(1);␊ + 5 | }␊ + 6 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | async function unicorn() {␊ + > 2 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 3 | for await (const a of b) {␊ + 4 | foo.includes(1);␊ + 5 | }␊ + 6 | }␊ + ` + +## Invalid #5 + 1 | const foo = [1, 2, 3]; + 2 | for (let i = 0; i < n; i++) { + 3 | foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | for (let i = 0; i < n; i++) {␊ + 3 | foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | for (let i = 0; i < n; i++) {␊ + 3 | foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #6 + 1 | const foo = [1, 2, 3]; + 2 | for (let a in b) { + 3 | foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | for (let a in b) {␊ + 3 | foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | for (let a in b) {␊ + 3 | foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #7 + 1 | const foo = [1, 2, 3]; + 2 | while (a) { + 3 | foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | while (a) {␊ + 3 | foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | while (a) {␊ + 3 | foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #8 + 1 | const foo = [1, 2, 3]; + 2 | do { + 3 | foo.includes(1); + 4 | } while (a) + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | do {␊ + 3 | foo.has(1);␊ + 4 | } while (a)␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | do {␊ + 3 | foo.includes(1);␊ + 4 | } while (a)␊ + ` + +## Invalid #9 + 1 | const foo = [1, 2, 3]; + 2 | do { + 3 | // … + 4 | } while (foo.includes(1)) + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | do {␊ + 3 | // …␊ + 4 | } while (foo.has(1))␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | do {␊ + 3 | // …␊ + 4 | } while (foo.includes(1))␊ + ` + +## Invalid #10 + 1 | const foo = [1, 2, 3]; + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #11 + 1 | const foo = [1, 2, 3]; + 2 | function * unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | function * unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function * unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #12 + 1 | const foo = [1, 2, 3]; + 2 | async function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | async function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | async function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #13 + 1 | const foo = [1, 2, 3]; + 2 | async function * unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | async function * unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | async function * unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #14 + 1 | const foo = [1, 2, 3]; + 2 | const unicorn = function () { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | const unicorn = function () {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | const unicorn = function () {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #15 + 1 | const foo = [1, 2, 3]; + 2 | const unicorn = () => foo.includes(1); + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | const unicorn = () => foo.has(1);␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | const unicorn = () => foo.includes(1);␊ + ` + +## Invalid #16 + 1 | const foo = [1, 2, 3]; + 2 | const a = { + 3 | b() { + 4 | return foo.includes(1); + 5 | } + 6 | }; + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | const a = {␊ + 3 | b() {␊ + 4 | return foo.has(1);␊ + 5 | }␊ + 6 | };␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | const a = {␊ + 3 | b() {␊ + 4 | return foo.includes(1);␊ + 5 | }␊ + 6 | };␊ + ` + +## Invalid #17 + 1 | const foo = [1, 2, 3]; + 2 | class A { + 3 | b() { + 4 | return foo.includes(1); + 5 | } + 6 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | class A {␊ + 3 | b() {␊ + 4 | return foo.has(1);␊ + 5 | }␊ + 6 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | class A {␊ + 3 | b() {␊ + 4 | return foo.includes(1);␊ + 5 | }␊ + 6 | }␊ + ` + +## Invalid #18 + 1 | const foo = [...bar]; + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + 5 | bar.pop(); + +> Output + + `␊ + 1 | const foo = new Set([...bar]);␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + 5 | bar.pop();␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [...bar];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + 5 | bar.pop();␊ + ` + +## Invalid #19 + 1 | const foo = [1, 2, 3]; + 2 | function unicorn() { + 3 | const exists = foo.includes(1); + 4 | function isExists(find) { + 5 | return foo.includes(find); + 6 | } + 7 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | function unicorn() {␊ + 3 | const exists = foo.has(1);␊ + 4 | function isExists(find) {␊ + 5 | return foo.has(find);␊ + 6 | }␊ + 7 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | const exists = foo.includes(1);␊ + 4 | function isExists(find) {␊ + 5 | return foo.includes(find);␊ + 6 | }␊ + 7 | }␊ + ` + +## Invalid #20 + 1 | function wrap() { + 2 | const foo = [1, 2, 3]; + 3 | + 4 | function unicorn() { + 5 | return foo.includes(1); + 6 | } + 7 | } + 8 | + 9 | const bar = [4, 5, 6]; + 10 | + 11 | function unicorn() { + 12 | return bar.includes(1); + 13 | } + +> Output + + `␊ + 1 | function wrap() {␊ + 2 | const foo = new Set([1, 2, 3]);␊ + 3 |␊ + 4 | function unicorn() {␊ + 5 | return foo.has(1);␊ + 6 | }␊ + 7 | }␊ + 8 |␊ + 9 | const bar = new Set([4, 5, 6]);␊ + 10 |␊ + 11 | function unicorn() {␊ + 12 | return bar.has(1);␊ + 13 | }␊ + ` + +> Error 1/2 + + `␊ + 1 | function wrap() {␊ + > 2 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 3 |␊ + 4 | function unicorn() {␊ + 5 | return foo.includes(1);␊ + 6 | }␊ + 7 | }␊ + 8 |␊ + 9 | const bar = [4, 5, 6];␊ + 10 |␊ + 11 | function unicorn() {␊ + 12 | return bar.includes(1);␊ + 13 | }␊ + ` + +> Error 2/2 + + `␊ + 1 | function wrap() {␊ + 2 | const foo = [1, 2, 3];␊ + 3 |␊ + 4 | function unicorn() {␊ + 5 | return foo.includes(1);␊ + 6 | }␊ + 7 | }␊ + 8 |␊ + > 9 | const bar = [4, 5, 6];␊ + | ^^^ \`bar\` should be a \`Set\`, and use \`bar.has()\` to check existence or non-existence.␊ + 10 |␊ + 11 | function unicorn() {␊ + 12 | return bar.includes(1);␊ + 13 | }␊ + ` + +## Invalid #21 + 1 | const foo = [1, 2, 3]; + 2 | function wrap() { + 3 | const exists = foo.includes(1); + 4 | const bar = [1, 2, 3]; + 5 | + 6 | function outer(find) { + 7 | const foo = [1, 2, 3]; + 8 | while (a) { + 9 | foo.includes(1); + 10 | } + 11 | + 12 | function inner(find) { + 13 | const bar = [1, 2, 3]; + 14 | while (a) { + 15 | const exists = bar.includes(1); + 16 | } + 17 | } + 18 | } + 19 | } + +> Output + + `␊ + 1 | const foo = new Set([1, 2, 3]);␊ + 2 | function wrap() {␊ + 3 | const exists = foo.has(1);␊ + 4 | const bar = [1, 2, 3];␊ + 5 |␊ + 6 | function outer(find) {␊ + 7 | const foo = new Set([1, 2, 3]);␊ + 8 | while (a) {␊ + 9 | foo.has(1);␊ + 10 | }␊ + 11 |␊ + 12 | function inner(find) {␊ + 13 | const bar = new Set([1, 2, 3]);␊ + 14 | while (a) {␊ + 15 | const exists = bar.has(1);␊ + 16 | }␊ + 17 | }␊ + 18 | }␊ + 19 | }␊ + ` + +> Error 1/3 + + `␊ + > 1 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function wrap() {␊ + 3 | const exists = foo.includes(1);␊ + 4 | const bar = [1, 2, 3];␊ + 5 |␊ + 6 | function outer(find) {␊ + 7 | const foo = [1, 2, 3];␊ + 8 | while (a) {␊ + 9 | foo.includes(1);␊ + 10 | }␊ + 11 |␊ + 12 | function inner(find) {␊ + 13 | const bar = [1, 2, 3];␊ + 14 | while (a) {␊ + 15 | const exists = bar.includes(1);␊ + 16 | }␊ + 17 | }␊ + 18 | }␊ + 19 | }␊ + ` + +> Error 2/3 + + `␊ + 1 | const foo = [1, 2, 3];␊ + 2 | function wrap() {␊ + 3 | const exists = foo.includes(1);␊ + 4 | const bar = [1, 2, 3];␊ + 5 |␊ + 6 | function outer(find) {␊ + > 7 | const foo = [1, 2, 3];␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 8 | while (a) {␊ + 9 | foo.includes(1);␊ + 10 | }␊ + 11 |␊ + 12 | function inner(find) {␊ + 13 | const bar = [1, 2, 3];␊ + 14 | while (a) {␊ + 15 | const exists = bar.includes(1);␊ + 16 | }␊ + 17 | }␊ + 18 | }␊ + 19 | }␊ + ` + +> Error 3/3 + + `␊ + 1 | const foo = [1, 2, 3];␊ + 2 | function wrap() {␊ + 3 | const exists = foo.includes(1);␊ + 4 | const bar = [1, 2, 3];␊ + 5 |␊ + 6 | function outer(find) {␊ + 7 | const foo = [1, 2, 3];␊ + 8 | while (a) {␊ + 9 | foo.includes(1);␊ + 10 | }␊ + 11 |␊ + 12 | function inner(find) {␊ + > 13 | const bar = [1, 2, 3];␊ + | ^^^ \`bar\` should be a \`Set\`, and use \`bar.has()\` to check existence or non-existence.␊ + 14 | while (a) {␊ + 15 | const exists = bar.includes(1);␊ + 16 | }␊ + 17 | }␊ + 18 | }␊ + 19 | }␊ + ` + +## Invalid #22 + 1 | const foo = Array(1, 2); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(Array(1, 2));␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = Array(1, 2);␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #23 + 1 | const foo = new Array(1, 2); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(new Array(1, 2));␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = new Array(1, 2);␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #24 + 1 | const foo = Array.from({length: 1}, (_, index) => index); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(Array.from({length: 1}, (_, index) => index));␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = Array.from({length: 1}, (_, index) => index);␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #25 + 1 | const foo = Array.of(1, 2); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(Array.of(1, 2));␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = Array.of(1, 2);␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #26 + 1 | const foo = bar.concat(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.concat());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.concat();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #27 + 1 | const foo = bar.copyWithin(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.copyWithin());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.copyWithin();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #28 + 1 | const foo = bar.fill(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.fill());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.fill();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #29 + 1 | const foo = bar.filter(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.filter());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.filter();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #30 + 1 | const foo = bar.flat(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.flat());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.flat();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #31 + 1 | const foo = bar.flatMap(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.flatMap());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.flatMap();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #32 + 1 | const foo = bar.map(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.map());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.map();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #33 + 1 | const foo = bar.reverse(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.reverse());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.reverse();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #34 + 1 | const foo = bar.slice(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.slice());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.slice();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #35 + 1 | const foo = bar.sort(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.sort());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.sort();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #36 + 1 | const foo = bar.splice(); + 2 | function unicorn() { + 3 | return foo.includes(1); + 4 | } + +> Output + + `␊ + 1 | const foo = new Set(bar.splice());␊ + 2 | function unicorn() {␊ + 3 | return foo.has(1);␊ + 4 | }␊ + ` + +> Error 1/1 + + `␊ + > 1 | const foo = bar.splice();␊ + | ^^^ \`foo\` should be a \`Set\`, and use \`foo.has()\` to check existence or non-existence.␊ + 2 | function unicorn() {␊ + 3 | return foo.includes(1);␊ + 4 | }␊ + ` + +## Invalid #37 + 1 | const foo = _([1,2,3]); + 2 | const bar = foo.map(value => value); + 3 | function unicorn() { + 4 | return bar.includes(1); + 5 | } + +> Output + + `␊ + 1 | const foo = _([1,2,3]);␊ + 2 | const bar = new Set(foo.map(value => value));␊ + 3 | function unicorn() {␊ + 4 | return bar.has(1);␊ + 5 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | const foo = _([1,2,3]);␊ + > 2 | const bar = foo.map(value => value);␊ + | ^^^ \`bar\` should be a \`Set\`, and use \`bar.has()\` to check existence or non-existence.␊ + 3 | function unicorn() {␊ + 4 | return bar.includes(1);␊ + 5 | }␊ + ` + +## Invalid #1 + 1 | const a: Array<'foo' | 'bar'> = ['foo', 'bar'] + 2 | + 3 | for (let i = 0; i < 3; i++) { + 4 | if (a.includes(someString)) { + 5 | console.log(123) + 6 | } + 7 | } + +> Error 1/1 + + `␊ + > 1 | const a: Array<'foo' | 'bar'> = ['foo', 'bar']␊ + | ^^^^^^^^^^^^^^^^^^^^^^^ \`a\` should be a \`Set\`, and use \`a.has()\` to check existence or non-existence.␊ + 2 |␊ + 3 | for (let i = 0; i < 3; i++) {␊ + 4 | if (a.includes(someString)) {␊ + 5 | console.log(123)␊ + 6 | }␊ + 7 | }␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch \`a\` to \`Set\`.␊ + 1 | const a: Array<'foo' | 'bar'> = new Set(['foo', 'bar'])␊ + 2 |␊ + 3 | for (let i = 0; i < 3; i++) {␊ + 4 | if (a.has(someString)) {␊ + 5 | console.log(123)␊ + 6 | }␊ + 7 | }␊ + ` diff --git a/test/snapshots/prefer-set-has.mjs.snap b/test/snapshots/prefer-set-has.mjs.snap new file mode 100644 index 0000000000..f61e80a7d2 Binary files /dev/null and b/test/snapshots/prefer-set-has.mjs.snap differ