From f2e63b01bccbaa92009176294d697378503ade31 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 4 Feb 2024 14:29:18 -0500 Subject: [PATCH] chore: enable no-confusing-void-expression internally --- .eslintrc.js | 1 - packages/ast-spec/tests/fixtures.test.ts | 4 +- .../src/rules/no-poorly-typed-ts-props.ts | 3 +- .../src/rules/plugin-test-formatting.ts | 18 +- .../src/rules/prefer-ast-types-enum.ts | 3 +- packages/eslint-plugin/src/rules/ban-types.ts | 3 +- .../rules/explicit-function-return-type.ts | 12 +- .../rules/explicit-module-boundary-types.ts | 52 ++++-- .../src/rules/func-call-spacing.ts | 3 +- packages/eslint-plugin/src/rules/indent.ts | 28 ++- .../src/rules/lines-around-comment.ts | 2 +- .../src/rules/member-ordering.ts | 3 +- .../src/rules/no-confusing-void-expression.ts | 18 +- .../src/rules/no-dupe-class-members.ts | 2 +- .../src/rules/no-extra-parens.ts | 93 ++++++---- .../src/rules/no-restricted-imports.ts | 15 +- .../eslint-plugin/src/rules/no-type-alias.ts | 5 +- .../src/rules/no-unnecessary-condition.ts | 26 ++- .../src/rules/no-unsafe-return.ts | 6 +- .../src/rules/prefer-regexp-exec.ts | 15 +- .../src/rules/promise-function-async.ts | 3 +- .../src/rules/restrict-plus-operands.ts | 6 +- .../src/rules/sort-type-constituents.ts | 3 +- packages/eslint-plugin/tests/docs.test.ts | 6 +- .../src/utils/validationHelpers.ts | 12 +- packages/rule-tester/tests/RuleTester.test.ts | 10 +- .../src/referencer/ClassVisitor.ts | 24 ++- .../src/referencer/Referencer.ts | 4 +- packages/scope-manager/src/scope/ScopeBase.ts | 4 +- packages/scope-manager/src/scope/WithScope.ts | 4 +- .../tests/eslint-scope/references.test.ts | 18 +- packages/scope-manager/tests/fixtures.test.ts | 4 +- .../type-utils/tests/isTypeReadonly.test.ts | 15 +- packages/types/tools/copy-ast-spec.ts | 12 +- .../getWatchProgramsForProjects.ts | 18 +- .../tests/lib/persistentParse.test.ts | 160 +++++++++++++----- .../tests/lib/semanticInfo.test.ts | 4 +- .../src/components/OptionsSelector.tsx | 20 ++- .../website/src/components/Playground.tsx | 4 +- .../src/components/RulesTable/index.tsx | 41 +++-- .../src/components/config/ConfigEditor.tsx | 13 +- .../src/components/editor/LoadedEditor.tsx | 40 +++-- .../src/components/inputs/Checkbox.tsx | 6 +- .../website/src/components/inputs/Text.tsx | 4 +- .../src/components/layout/EditorTabs.tsx | 4 +- .../src/components/lib/createEventsBinder.ts | 4 +- .../website/src/components/linter/bridge.ts | 4 +- .../typeDetails/SimplifiedTreeView.tsx | 3 +- packages/website/src/hooks/useBool.ts | 7 +- packages/website/src/hooks/useMediaQuery.ts | 3 +- .../src/theme/CodeBlock/Content/String.tsx | 4 +- 51 files changed, 523 insertions(+), 253 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 1398b8f04d87..1e542e149e59 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -52,7 +52,6 @@ module.exports = { 'deprecation/deprecation': 'error', // TODO(#7130): Investigate changing these in or removing these from presets - '@typescript-eslint/no-confusing-void-expression': 'off', '@typescript-eslint/prefer-string-starts-ends-with': 'off', // diff --git a/packages/ast-spec/tests/fixtures.test.ts b/packages/ast-spec/tests/fixtures.test.ts index d107cc320255..bffaf911a814 100644 --- a/packages/ast-spec/tests/fixtures.test.ts +++ b/packages/ast-spec/tests/fixtures.test.ts @@ -333,7 +333,9 @@ function nestDescribe(fixture: Fixture, segments = fixture.segments): void { } describe('AST Fixtures', () => { - FIXTURES.forEach(f => nestDescribe(f)); + FIXTURES.forEach(f => { + nestDescribe(f); + }); // once we've run all the tests, snapshot the list of fixtures that have differences for easy reference it('List fixtures with AST differences', () => { diff --git a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts index 1d07e54351b4..1b0bbdb57ad1 100644 --- a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts +++ b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts @@ -73,7 +73,7 @@ export default createRule({ continue; } - return context.report({ + context.report({ node, messageId: banned.fixWith ? 'doNotUseWithFixer' : 'doNotUse', data: banned, @@ -87,6 +87,7 @@ export default createRule({ }, ], }); + return; } }, }; diff --git a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts index 4c13b42b9cc5..76a635ffba5c 100644 --- a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts +++ b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts @@ -274,7 +274,7 @@ export default createRule({ if (literal.loc.end.line === literal.loc.start.line) { // don't use template strings for single line tests - return context.report({ + context.report({ node: literal, messageId: 'singleLineQuotes', fix(fixer) { @@ -295,6 +295,7 @@ export default createRule({ ]; }, }); + return; } const lines = text.split('\n'); @@ -305,7 +306,7 @@ export default createRule({ const isEndEmpty = lastLine.trimStart() === ''; if (!isStartEmpty || !isEndEmpty) { // multiline template strings must have an empty first/last line - return context.report({ + context.report({ node: literal, messageId: 'templateLiteralEmptyEnds', *fix(fixer) { @@ -324,11 +325,12 @@ export default createRule({ } }, }); + return; } const parentIndent = getExpectedIndentForNode(literal, sourceCode.lines); if (lastLine.length !== parentIndent) { - return context.report({ + context.report({ node: literal, messageId: 'templateLiteralLastLineIndent', fix(fixer) { @@ -338,6 +340,7 @@ export default createRule({ ); }, }); + return; } // remove the empty lines @@ -353,13 +356,14 @@ export default createRule({ const requiresIndent = firstLineIndent.length > 0; if (requiresIndent) { if (firstLineIndent.length !== expectedIndent) { - return context.report({ + context.report({ node: literal, messageId: 'templateStringRequiresIndent', data: { indent: expectedIndent, }, }); + return; } // quick-and-dirty validation that lines are roughly indented correctly @@ -373,13 +377,14 @@ export default createRule({ const indent = matches[1]; if (indent.length < expectedIndent) { - return context.report({ + context.report({ node: literal, messageId: 'templateStringMinimumIndent', data: { indent: expectedIndent, }, }); + return; } } @@ -404,7 +409,7 @@ export default createRule({ .join('\n') : formatted; - return context.report({ + context.report({ node: literal, messageId: isErrorTest ? 'invalidFormattingErrorTest' @@ -419,6 +424,7 @@ export default createRule({ ); }, }); + return; } } diff --git a/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts b/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts index 9e97e44d2536..ffbfa8716f9e 100755 --- a/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts +++ b/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts @@ -28,7 +28,7 @@ export default createRule({ const report = ( enumName: 'AST_NODE_TYPES' | 'AST_TOKEN_TYPES' | 'DefinitionType', literal: TSESTree.StringLiteral, - ): void => + ): void => { context.report({ data: { enumName, literal: literal.value }, messageId: 'preferEnum', @@ -36,6 +36,7 @@ export default createRule({ fix: fixer => fixer.replaceText(literal, `${enumName}.${literal.value}`), }); + }; return { Literal(node: TSESTree.Literal): void { diff --git a/packages/eslint-plugin/src/rules/ban-types.ts b/packages/eslint-plugin/src/rules/ban-types.ts index 574c16937e98..10418463c75b 100644 --- a/packages/eslint-plugin/src/rules/ban-types.ts +++ b/packages/eslint-plugin/src/rules/ban-types.ts @@ -261,8 +261,9 @@ export default createRule({ TYPE_KEYWORDS, (acc: TSESLint.RuleListener, keyword) => { if (bannedTypes.has(keyword)) { - acc[TYPE_KEYWORDS[keyword]] = (node: TSESTree.Node): void => + acc[TYPE_KEYWORDS[keyword]] = (node: TSESTree.Node): void => { checkBannedTypes(node, keyword); + }; } return acc; diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index e6201df8e9e6..37d6007fe14b 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -196,13 +196,13 @@ export default createRule({ return; } - checkFunctionReturnType(node, options, sourceCode, loc => + checkFunctionReturnType(node, options, sourceCode, loc => { context.report({ node, loc, messageId: 'missingReturnType', - }), - ); + }); + }); }, FunctionDeclaration(node): void { if (isAllowedFunction(node)) { @@ -212,13 +212,13 @@ export default createRule({ return; } - checkFunctionReturnType(node, options, sourceCode, loc => + checkFunctionReturnType(node, options, sourceCode, loc => { context.report({ node, loc, messageId: 'missingReturnType', - }), - ); + }); + }); }, }; }, diff --git a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts index 092179f8187d..fe65dc1fbba4 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -213,8 +213,10 @@ export default createRule({ } return; - case AST_NODE_TYPES.TSParameterProperty: - return checkParameter(param.parameter); + case AST_NODE_TYPES.TSParameterProperty: { + checkParameter(param.parameter); + return; + } case AST_NODE_TYPES.AssignmentPattern: // ignored as it has a type via its assignment return; @@ -338,8 +340,10 @@ export default createRule({ switch (node.type) { case AST_NODE_TYPES.ArrowFunctionExpression: - case AST_NODE_TYPES.FunctionExpression: - return checkFunctionExpression(node); + case AST_NODE_TYPES.FunctionExpression: { + checkFunctionExpression(node); + return; + } case AST_NODE_TYPES.ArrayExpression: for (const element of node.elements) { @@ -354,7 +358,10 @@ export default createRule({ ) { return; } - return checkNode(node.value); + { + checkNode(node.value); + return; + } case AST_NODE_TYPES.ClassDeclaration: case AST_NODE_TYPES.ClassExpression: @@ -363,8 +370,10 @@ export default createRule({ } return; - case AST_NODE_TYPES.FunctionDeclaration: - return checkFunction(node); + case AST_NODE_TYPES.FunctionDeclaration: { + checkFunction(node); + return; + } case AST_NODE_TYPES.MethodDefinition: case AST_NODE_TYPES.TSAbstractMethodDefinition: @@ -374,10 +383,15 @@ export default createRule({ ) { return; } - return checkNode(node.value); + { + checkNode(node.value); + return; + } - case AST_NODE_TYPES.Identifier: - return followReference(node); + case AST_NODE_TYPES.Identifier: { + followReference(node); + return; + } case AST_NODE_TYPES.ObjectExpression: for (const property of node.properties) { @@ -385,11 +399,15 @@ export default createRule({ } return; - case AST_NODE_TYPES.Property: - return checkNode(node.value); + case AST_NODE_TYPES.Property: { + checkNode(node.value); + return; + } - case AST_NODE_TYPES.TSEmptyBodyFunctionExpression: - return checkEmptyBodyFunctionExpression(node); + case AST_NODE_TYPES.TSEmptyBodyFunctionExpression: { + checkEmptyBodyFunctionExpression(node); + return; + } case AST_NODE_TYPES.VariableDeclaration: for (const declaration of node.declarations) { @@ -397,8 +415,10 @@ export default createRule({ } return; - case AST_NODE_TYPES.VariableDeclarator: - return checkNode(node.init); + case AST_NODE_TYPES.VariableDeclarator: { + checkNode(node.init); + return; + } } } diff --git a/packages/eslint-plugin/src/rules/func-call-spacing.ts b/packages/eslint-plugin/src/rules/func-call-spacing.ts index 510730fca997..c05f8946c315 100644 --- a/packages/eslint-plugin/src/rules/func-call-spacing.ts +++ b/packages/eslint-plugin/src/rules/func-call-spacing.ts @@ -117,7 +117,7 @@ export default createRule({ if (option === 'never') { if (hasWhitespace) { - return context.report({ + context.report({ node, loc: lastCalleeToken.loc.start, messageId: 'unexpectedWhitespace', @@ -140,6 +140,7 @@ export default createRule({ return null; }, }); + return; } } else if (isOptionalCall) { // disallow: diff --git a/packages/eslint-plugin/src/rules/indent.ts b/packages/eslint-plugin/src/rules/indent.ts index c2d61583405a..d97d853278eb 100644 --- a/packages/eslint-plugin/src/rules/indent.ts +++ b/packages/eslint-plugin/src/rules/indent.ts @@ -197,12 +197,12 @@ export default createRule({ return; } - return rules.VariableDeclaration(node); + rules.VariableDeclaration(node); }, TSAsExpression(node: TSESTree.TSAsExpression) { // transform it to a BinaryExpression - return rules['BinaryExpression, LogicalExpression']({ + rules['BinaryExpression, LogicalExpression']({ type: AST_NODE_TYPES.BinaryExpression, operator: 'as' as any, left: node.expression, @@ -218,7 +218,7 @@ export default createRule({ TSConditionalType(node: TSESTree.TSConditionalType) { // transform it to a ConditionalExpression - return rules.ConditionalExpression({ + rules.ConditionalExpression({ type: AST_NODE_TYPES.ConditionalExpression, test: { parent: node, @@ -248,7 +248,7 @@ export default createRule({ node: TSESTree.TSEnumDeclaration | TSESTree.TSTypeLiteral, ) { // transform it to an ObjectExpression - return rules['ObjectExpression, ObjectPattern']({ + rules['ObjectExpression, ObjectPattern']({ type: AST_NODE_TYPES.ObjectExpression, properties: ( node.members as (TSESTree.TSEnumMember | TSESTree.TypeElement)[] @@ -269,7 +269,7 @@ export default createRule({ // use VariableDeclaration instead of ImportDeclaration because it's essentially the same thing const { id, moduleReference } = node; - return rules.VariableDeclaration({ + rules.VariableDeclaration({ type: AST_NODE_TYPES.VariableDeclaration, kind: 'const' as const, declarations: [ @@ -320,7 +320,7 @@ export default createRule({ TSIndexedAccessType(node: TSESTree.TSIndexedAccessType) { // convert to a MemberExpression - return rules['MemberExpression, JSXMemberExpression, MetaProperty']({ + rules['MemberExpression, JSXMemberExpression, MetaProperty']({ type: AST_NODE_TYPES.MemberExpression, object: node.objectType as any, property: node.indexType as any, @@ -336,7 +336,7 @@ export default createRule({ TSInterfaceBody(node: TSESTree.TSInterfaceBody) { // transform it to an ClassBody - return rules['BlockStatement, ClassBody']({ + rules['BlockStatement, ClassBody']({ type: AST_NODE_TYPES.ClassBody, body: node.body.map( p => @@ -357,9 +357,7 @@ export default createRule({ node: TSESTree.TSInterfaceDeclaration, ) { // transform it to a ClassDeclaration - return rules[ - 'ClassDeclaration[superClass], ClassExpression[superClass]' - ]({ + rules['ClassDeclaration[superClass], ClassExpression[superClass]']({ type: AST_NODE_TYPES.ClassDeclaration, body: node.body as any, id: null, @@ -387,7 +385,7 @@ export default createRule({ )!; // transform it to an ObjectExpression - return rules['ObjectExpression, ObjectPattern']({ + rules['ObjectExpression, ObjectPattern']({ type: AST_NODE_TYPES.ObjectExpression, properties: [ { @@ -426,7 +424,7 @@ export default createRule({ TSModuleBlock(node: TSESTree.TSModuleBlock) { // transform it to a BlockStatement - return rules['BlockStatement, ClassBody']({ + rules['BlockStatement, ClassBody']({ type: AST_NODE_TYPES.BlockStatement, body: node.body as any, @@ -438,7 +436,7 @@ export default createRule({ }, TSQualifiedName(node: TSESTree.TSQualifiedName) { - return rules['MemberExpression, JSXMemberExpression, MetaProperty']({ + rules['MemberExpression, JSXMemberExpression, MetaProperty']({ type: AST_NODE_TYPES.MemberExpression, object: node.left as any, property: node.right as any, @@ -454,7 +452,7 @@ export default createRule({ TSTupleType(node: TSESTree.TSTupleType) { // transform it to an ArrayExpression - return rules['ArrayExpression, ArrayPattern']({ + rules['ArrayExpression, ArrayPattern']({ type: AST_NODE_TYPES.ArrayExpression, elements: node.elementTypes as any, @@ -474,7 +472,7 @@ export default createRule({ // JSX is about the closest we can get because the angle brackets // it's not perfect but it works! - return rules.JSXOpeningElement({ + rules.JSXOpeningElement({ type: AST_NODE_TYPES.JSXOpeningElement, selfClosing: false, name: name as any, diff --git a/packages/eslint-plugin/src/rules/lines-around-comment.ts b/packages/eslint-plugin/src/rules/lines-around-comment.ts index 9c25d24351a6..c37eb1eee84c 100644 --- a/packages/eslint-plugin/src/rules/lines-around-comment.ts +++ b/packages/eslint-plugin/src/rules/lines-around-comment.ts @@ -410,7 +410,7 @@ export default createRule({ } } } - return context.report(descriptor); + context.report(descriptor); }; const customContext = { report: customReport }; diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index 34fed637e6c8..069004bc4ac6 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -880,7 +880,7 @@ export default createRule({ i && isMemberOptional(member) !== isMemberOptional(members[i - 1]), ); - const report = (member: Member): void => + const report = (member: Member): void => { context.report({ messageId: 'incorrectRequiredMembersOrder', loc: member.loc, @@ -890,6 +890,7 @@ export default createRule({ optionalityOrder === 'required-first' ? 'required' : 'optional', }, }); + }; // if the optionality of the first item is correct (based on optionalityOrder) // then the first 0 inclusive to switchIndex exclusive members all diff --git a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts index 3eae588d0079..57654487e920 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -115,16 +115,17 @@ export default createRule({ if (options.ignoreVoidOperator) { // handle wrapping with `void` - return context.report({ + context.report({ node, messageId: 'invalidVoidExprArrowWrapVoid', fix: wrapVoidFix, }); + return; } // handle wrapping with braces const arrowFunction = invalidAncestor; - return context.report({ + context.report({ node, messageId: 'invalidVoidExprArrow', fix(fixer) { @@ -151,6 +152,7 @@ export default createRule({ return fixer.replaceText(arrowBody, newArrowBodyText); }, }); + return; } if (invalidAncestor.type === AST_NODE_TYPES.ReturnStatement) { @@ -158,18 +160,19 @@ export default createRule({ if (options.ignoreVoidOperator) { // handle wrapping with `void` - return context.report({ + context.report({ node, messageId: 'invalidVoidExprReturnWrapVoid', fix: wrapVoidFix, }); + return; } const returnStmt = invalidAncestor; if (isFinalReturn(returnStmt)) { // remove the `return` keyword - return context.report({ + context.report({ node, messageId: 'invalidVoidExprReturnLast', fix(fixer) { @@ -186,10 +189,11 @@ export default createRule({ return fixer.replaceText(returnStmt, newReturnStmtText); }, }); + return; } // move before the `return` keyword - return context.report({ + context.report({ node, messageId: 'invalidVoidExprReturn', fix(fixer) { @@ -208,16 +212,18 @@ export default createRule({ return fixer.replaceText(returnStmt, newReturnStmtText); }, }); + return; } // handle generic case if (options.ignoreVoidOperator) { // this would be reported by this rule btw. such irony - return context.report({ + context.report({ node, messageId: 'invalidVoidExprWrapVoid', suggest: [{ messageId: 'voidExprWrapVoid', fix: wrapVoidFix }], }); + return; } context.report({ diff --git a/packages/eslint-plugin/src/rules/no-dupe-class-members.ts b/packages/eslint-plugin/src/rules/no-dupe-class-members.ts index 09c734a75585..26691f222345 100644 --- a/packages/eslint-plugin/src/rules/no-dupe-class-members.ts +++ b/packages/eslint-plugin/src/rules/no-dupe-class-members.ts @@ -44,7 +44,7 @@ export default createRule({ return; } - return coreListener(node); + coreListener(node); }; } diff --git a/packages/eslint-plugin/src/rules/no-extra-parens.ts b/packages/eslint-plugin/src/rules/no-extra-parens.ts index 8360df8e3ee4..e1e3d858322c 100644 --- a/packages/eslint-plugin/src/rules/no-extra-parens.ts +++ b/packages/eslint-plugin/src/rules/no-extra-parens.ts @@ -49,25 +49,27 @@ export default createRule({ return; // ignore } if (isLeftTypeAssertion) { - return rule({ + rule({ ...node, left: { ...node.left, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } if (isRightTypeAssertion) { - return rule({ + rule({ ...node, right: { ...node.right, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rule(node); + rule(node); } function callExp( node: TSESTree.CallExpression | TSESTree.NewExpression, @@ -76,13 +78,14 @@ export default createRule({ if (isTypeAssertion(node.callee)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped - return rule({ + rule({ ...node, callee: { ...node.callee, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } if ( @@ -91,7 +94,7 @@ export default createRule({ sourceCode.getTokenAfter(node.callee, isOpeningParenToken) !== sourceCode.getTokenBefore(node.arguments[0], isOpeningParenToken) ) { - return rule({ + rule({ ...node, arguments: [ { @@ -100,9 +103,10 @@ export default createRule({ }, ], }); + return; } - return rule(node); + rule(node); } function unaryUpdateExpression( node: TSESTree.UnaryExpression | TSESTree.UpdateExpression, @@ -111,125 +115,137 @@ export default createRule({ if (isTypeAssertion(node.argument)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped - return rule({ + rule({ ...node, argument: { ...node.argument, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rule(node); + rule(node); } const overrides: TSESLint.RuleListener = { // ArrayExpression ArrowFunctionExpression(node) { if (!isTypeAssertion(node.body)) { - return rules.ArrowFunctionExpression(node); + rules.ArrowFunctionExpression(node); + return; } }, // AssignmentExpression AwaitExpression(node) { if (isTypeAssertion(node.argument)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped - return rules.AwaitExpression({ + rules.AwaitExpression({ ...node, argument: { ...node.argument, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rules.AwaitExpression(node); + rules.AwaitExpression(node); }, BinaryExpression: binaryExp, CallExpression: callExp, ClassDeclaration(node) { if (node.superClass?.type === AST_NODE_TYPES.TSAsExpression) { - return rules.ClassDeclaration({ + rules.ClassDeclaration({ ...node, superClass: { ...node.superClass, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rules.ClassDeclaration(node); + rules.ClassDeclaration(node); }, ClassExpression(node) { if (node.superClass?.type === AST_NODE_TYPES.TSAsExpression) { - return rules.ClassExpression({ + rules.ClassExpression({ ...node, superClass: { ...node.superClass, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rules.ClassExpression(node); + rules.ClassExpression(node); }, ConditionalExpression(node) { // reduces the precedence of the node so the rule thinks it needs to be wrapped if (isTypeAssertion(node.test)) { - return rules.ConditionalExpression({ + rules.ConditionalExpression({ ...node, test: { ...node.test, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } if (isTypeAssertion(node.consequent)) { - return rules.ConditionalExpression({ + rules.ConditionalExpression({ ...node, consequent: { ...node.consequent, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } if (isTypeAssertion(node.alternate)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped - return rules.ConditionalExpression({ + rules.ConditionalExpression({ ...node, alternate: { ...node.alternate, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rules.ConditionalExpression(node); + rules.ConditionalExpression(node); }, // DoWhileStatement // ForIn and ForOf are guarded by eslint version ForStatement(node) { // make the rule skip the piece by removing it entirely if (node.init && isTypeAssertion(node.init)) { - return rules.ForStatement({ + rules.ForStatement({ ...node, init: null, }); + return; } if (node.test && isTypeAssertion(node.test)) { - return rules.ForStatement({ + rules.ForStatement({ ...node, test: null, }); + return; } if (node.update && isTypeAssertion(node.update)) { - return rules.ForStatement({ + rules.ForStatement({ ...node, update: null, }); + return; } - return rules.ForStatement(node); + rules.ForStatement(node); }, 'ForStatement > *.init:exit'(node: TSESTree.Node) { if (!isTypeAssertion(node)) { - return rules['ForStatement > *.init:exit'](node); + rules['ForStatement > *.init:exit'](node); + return; } }, // IfStatement @@ -237,16 +253,17 @@ export default createRule({ MemberExpression(node) { if (isTypeAssertion(node.object)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped - return rules.MemberExpression({ + rules.MemberExpression({ ...node, object: { ...node.object, type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rules.MemberExpression(node); + rules.MemberExpression(node); }, NewExpression: callExp, // ObjectExpression @@ -254,18 +271,21 @@ export default createRule({ // SequenceExpression SpreadElement(node) { if (!isTypeAssertion(node.argument)) { - return rules.SpreadElement(node); + rules.SpreadElement(node); + return; } }, SwitchCase(node) { if (node.test && !isTypeAssertion(node.test)) { - return rules.SwitchCase(node); + rules.SwitchCase(node); + return; } }, // SwitchStatement ThrowStatement(node) { if (node.argument && !isTypeAssertion(node.argument)) { - return rules.ThrowStatement(node); + rules.ThrowStatement(node); + return; } }, UnaryExpression: unaryUpdateExpression, @@ -275,7 +295,8 @@ export default createRule({ // WithStatement - i'm not going to even bother implementing this terrible and never used feature YieldExpression(node) { if (node.argument && !isTypeAssertion(node.argument)) { - return rules.YieldExpression(node); + rules.YieldExpression(node); + return; } }, }; @@ -288,12 +309,12 @@ export default createRule({ return; } - return rules.ForInStatement(node); + rules.ForInStatement(node); }; overrides.ForOfStatement = function (node): void { if (isTypeAssertion(node.right)) { // makes the rule skip checking of the right - return rules.ForOfStatement({ + rules.ForOfStatement({ ...node, type: AST_NODE_TYPES.ForOfStatement, right: { @@ -301,9 +322,10 @@ export default createRule({ type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rules.ForOfStatement(node); + rules.ForOfStatement(node); }; } else { overrides['ForInStatement, ForOfStatement'] = function ( @@ -311,7 +333,7 @@ export default createRule({ ): void { if (isTypeAssertion(node.right)) { // makes the rule skip checking of the right - return rules['ForInStatement, ForOfStatement']({ + rules['ForInStatement, ForOfStatement']({ ...node, type: AST_NODE_TYPES.ForOfStatement as any, right: { @@ -319,9 +341,10 @@ export default createRule({ type: AST_NODE_TYPES.SequenceExpression as any, }, }); + return; } - return rules['ForInStatement, ForOfStatement'](node); + rules['ForInStatement, ForOfStatement'](node); }; } return Object.assign({}, rules, overrides); diff --git a/packages/eslint-plugin/src/rules/no-restricted-imports.ts b/packages/eslint-plugin/src/rules/no-restricted-imports.ts index b1e2d229f6a7..8026ad3fd18c 100644 --- a/packages/eslint-plugin/src/rules/no-restricted-imports.ts +++ b/packages/eslint-plugin/src/rules/no-restricted-imports.ts @@ -300,10 +300,12 @@ export default createRule({ !isAllowedTypeImportPath(importSource) && !isAllowedTypeImportPattern(importSource) ) { - return rules.ImportDeclaration(node); + rules.ImportDeclaration(node); + return; } } else { - return rules.ImportDeclaration(node); + rules.ImportDeclaration(node); + return; } } @@ -331,7 +333,8 @@ export default createRule({ }, ], } satisfies TSESTree.ImportDeclaration; - return checkImportNode(synthesizedImport); + checkImportNode(synthesizedImport); + return; } }, ImportDeclaration: checkImportNode, @@ -350,10 +353,12 @@ export default createRule({ !isAllowedTypeImportPath(importSource) && !isAllowedTypeImportPattern(importSource) ) { - return rules.ExportNamedDeclaration(node); + rules.ExportNamedDeclaration(node); + return; } } else { - return rules.ExportNamedDeclaration(node); + rules.ExportNamedDeclaration(node); + return; } }, ExportAllDeclaration: rules.ExportAllDeclaration, diff --git a/packages/eslint-plugin/src/rules/no-type-alias.ts b/packages/eslint-plugin/src/rules/no-type-alias.ts index b72c1f8b991a..57ffedecd21a 100644 --- a/packages/eslint-plugin/src/rules/no-type-alias.ts +++ b/packages/eslint-plugin/src/rules/no-type-alias.ts @@ -188,16 +188,17 @@ export default createRule({ type: string, ): void { if (isRoot) { - return context.report({ + context.report({ node, messageId: 'noTypeAlias', data: { alias: type.toLowerCase(), }, }); + return; } - return context.report({ + context.report({ node, messageId: 'noCompositionAlias', data: { diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 34ebfc018d6a..36639ccf26fc 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -232,7 +232,8 @@ export default createRule({ node.type === AST_NODE_TYPES.UnaryExpression && node.operator === '!' ) { - return checkNode(node.argument, true); + checkNode(node.argument, true); + return; } // Since typescript array index signature types don't represent the @@ -252,7 +253,8 @@ export default createRule({ node.type === AST_NODE_TYPES.LogicalExpression && node.operator !== '??' ) { - return checkNode(node.right); + checkNode(node.right); + return; } const type = getConstrainedTypeAtLocation(services, node); @@ -477,7 +479,8 @@ export default createRule({ // Two special cases, where we can directly check the node that's returned: // () => something if (callback.body.type !== AST_NODE_TYPES.BlockStatement) { - return checkNode(callback.body); + checkNode(callback.body); + return; } // () => { return something; } const callbackBody = callback.body.body; @@ -486,7 +489,8 @@ export default createRule({ callbackBody[0].type === AST_NODE_TYPES.ReturnStatement && callbackBody[0].argument ) { - return checkNode(callbackBody[0].argument); + checkNode(callbackBody[0].argument); + return; } // Potential enhancement: could use code-path analysis to check // any function with a single return statement @@ -507,16 +511,18 @@ export default createRule({ return; } if (!returnTypes.some(isPossiblyFalsy)) { - return context.report({ + context.report({ node: callback, messageId: 'alwaysTruthyFunc', }); + return; } if (!returnTypes.some(isPossiblyTruthy)) { - return context.report({ + context.report({ node: callback, messageId: 'alwaysFalsyFunc', }); + return; } } } @@ -716,10 +722,14 @@ export default createRule({ AssignmentExpression: checkAssignmentExpression, BinaryExpression: checkIfBinaryExpressionIsNecessaryConditional, CallExpression: checkCallExpression, - ConditionalExpression: (node): void => checkNode(node.test), + ConditionalExpression: (node): void => { + checkNode(node.test); + }, DoWhileStatement: checkIfLoopIsNecessaryConditional, ForStatement: checkIfLoopIsNecessaryConditional, - IfStatement: (node): void => checkNode(node.test), + IfStatement: (node): void => { + checkNode(node.test); + }, LogicalExpression: checkLogicalExpressionForUnnecessaryConditionals, WhileStatement: checkIfLoopIsNecessaryConditional, 'MemberExpression[optional = true]': checkOptionalMemberExpression, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-return.ts b/packages/eslint-plugin/src/rules/no-unsafe-return.ts index fa301bafa652..7fc94597b0b9 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-return.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-return.ts @@ -152,13 +152,14 @@ export default createRule({ } // If the function return type was not unknown/unknown[], mark usage as unsafeReturn. - return context.report({ + context.report({ node: reportingNode, messageId, data: { type: anyType === AnyType.Any ? 'any' : 'any[]', }, }); + return; } for (const signature of functionType.getCallSignatures()) { @@ -174,7 +175,7 @@ export default createRule({ } const { sender, receiver } = result; - return context.report({ + context.report({ node: reportingNode, messageId: 'unsafeReturnAssignment', data: { @@ -182,6 +183,7 @@ export default createRule({ receiver: checker.typeToString(receiver), }, }); + return; } } diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index 4669cc2a97c6..4cff91a19e84 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -125,7 +125,7 @@ export default createRule({ } catch { return; } - return context.report({ + context.report({ node: memberNode.property, messageId: 'regExpExecOverStringMatch', fix: getWrappingFixer({ @@ -135,6 +135,7 @@ export default createRule({ wrap: objectCode => `${regExp.toString()}.exec(${objectCode})`, }), }); + return; } const argumentType = services.getTypeAtLocation(argumentNode); @@ -142,8 +143,8 @@ export default createRule({ tsutils.unionTypeParts(argumentType), ); switch (argumentTypes) { - case ArgumentType.RegExp: - return context.report({ + case ArgumentType.RegExp: { + context.report({ node: memberNode.property, messageId: 'regExpExecOverStringMatch', fix: getWrappingFixer({ @@ -154,9 +155,11 @@ export default createRule({ `${argumentCode}.exec(${objectCode})`, }), }); + return; + } - case ArgumentType.String: - return context.report({ + case ArgumentType.String: { + context.report({ node: memberNode.property, messageId: 'regExpExecOverStringMatch', fix: getWrappingFixer({ @@ -167,6 +170,8 @@ export default createRule({ `RegExp(${argumentCode}).exec(${objectCode})`, }), }); + return; + } } }, }; diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 2c286cb45506..868563984804 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -142,11 +142,12 @@ export default createRule({ if (isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { // Report without auto fixer because the return type is unknown - return context.report({ + context.report({ messageId: 'missingAsync', node, loc: getFunctionHeadLoc(node, sourceCode), }); + return; } context.report({ diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index 9e17fa486b52..3ffc346510d2 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -208,7 +208,7 @@ export default createRule({ isTypeFlagSetInUnion(baseType, ts.TypeFlags.StringLike) && isTypeFlagSetInUnion(otherType, ts.TypeFlags.NumberLike) ) { - return context.report({ + context.report({ data: { stringLike, left: typeChecker.typeToString(leftType), @@ -217,13 +217,14 @@ export default createRule({ messageId: 'mismatched', node, }); + return; } if ( isTypeFlagSetInUnion(baseType, ts.TypeFlags.NumberLike) && isTypeFlagSetInUnion(otherType, ts.TypeFlags.BigIntLike) ) { - return context.report({ + context.report({ data: { left: typeChecker.typeToString(leftType), right: typeChecker.typeToString(rightType), @@ -231,6 +232,7 @@ export default createRule({ messageId: 'bigintAndNumber', node, }); + return; } } } diff --git a/packages/eslint-plugin/src/rules/sort-type-constituents.ts b/packages/eslint-plugin/src/rules/sort-type-constituents.ts index 856ed2067727..d48de4b350b6 100644 --- a/packages/eslint-plugin/src/rules/sort-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/sort-type-constituents.ts @@ -232,7 +232,7 @@ export default createRule({ return fixer.replaceText(node, sorted); }; - return context.report({ + context.report({ node, messageId, data, @@ -249,6 +249,7 @@ export default createRule({ } : { fix }), }); + return; } } } diff --git a/packages/eslint-plugin/tests/docs.test.ts b/packages/eslint-plugin/tests/docs.test.ts index 9d99ca159103..965d86bc653c 100644 --- a/packages/eslint-plugin/tests/docs.test.ts +++ b/packages/eslint-plugin/tests/docs.test.ts @@ -107,9 +107,9 @@ describe('Validating rule docs', () => { // Get all H2 headings objects as the other levels are variable by design. const headings = tokens.filter(tokenIsH2); - headings.forEach(heading => - expect(heading.text).toBe(titleCase(heading.text)), - ); + headings.forEach(heading => { + expect(heading.text).toBe(titleCase(heading.text)); + }); }); const headings = tokens.filter(tokenIsHeading); diff --git a/packages/rule-tester/src/utils/validationHelpers.ts b/packages/rule-tester/src/utils/validationHelpers.ts index 34e0ca3277de..72885c4aef97 100644 --- a/packages/rule-tester/src/utils/validationHelpers.ts +++ b/packages/rule-tester/src/utils/validationHelpers.ts @@ -111,10 +111,16 @@ export function wrapParser(parser: Parser.ParserModule): Parser.ParserModule { simpleTraverse(ast, { visitorKeys: visitorKeys, - enter: node => defineStartEndAsError('node', node), + enter: node => { + defineStartEndAsError('node', node); + }, + }); + ast.tokens?.forEach(token => { + defineStartEndAsError('token', token); + }); + ast.comments?.forEach(comment => { + defineStartEndAsError('token', comment); }); - ast.tokens?.forEach(token => defineStartEndAsError('token', token)); - ast.comments?.forEach(comment => defineStartEndAsError('token', comment)); } if ('parseForESLint' in parser) { diff --git a/packages/rule-tester/tests/RuleTester.test.ts b/packages/rule-tester/tests/RuleTester.test.ts index 2cfc3678ad58..25faa360f2fc 100644 --- a/packages/rule-tester/tests/RuleTester.test.ts +++ b/packages/rule-tester/tests/RuleTester.test.ts @@ -60,7 +60,9 @@ jest.mock('@typescript-eslint/parser', () => { /* eslint-disable jest/prefer-spy-on -- we need to specifically assign to the properties or else it will use the global value and register actual tests! */ -const IMMEDIATE_CALLBACK: RuleTesterTestFrameworkFunctionBase = (_, cb) => cb(); +const IMMEDIATE_CALLBACK: RuleTesterTestFrameworkFunctionBase = (_, cb) => { + cb(); +}; RuleTester.afterAll = jest.fn(/* intentionally don't immediate callback here */); RuleTester.describe = jest.fn(IMMEDIATE_CALLBACK); @@ -309,7 +311,7 @@ describe('RuleTester', () => { }, }); - expect(() => + expect(() => { ruleTester.run('my-rule', NOOP_RULE, { valid: [ { @@ -319,8 +321,8 @@ describe('RuleTester', () => { ], invalid: [], - }), - ).toThrowErrorMatchingInlineSnapshot( + }); + }).toThrowErrorMatchingInlineSnapshot( `"Do not set the parser at the test level unless you want to use a parser other than "@typescript-eslint/parser""`, ); }); diff --git a/packages/scope-manager/src/referencer/ClassVisitor.ts b/packages/scope-manager/src/referencer/ClassVisitor.ts index 33b48c7a103b..d96131132d6e 100644 --- a/packages/scope-manager/src/referencer/ClassVisitor.ts +++ b/packages/scope-manager/src/referencer/ClassVisitor.ts @@ -57,7 +57,9 @@ class ClassVisitor extends Visitor { .defineIdentifier(node.id, new ClassNameDefinition(node.id, node)); } - node.decorators.forEach(d => this.#referencer.visit(d)); + node.decorators.forEach(d => { + this.#referencer.visit(d); + }); this.#referencer.scopeManager.nestClassScope(node); @@ -75,7 +77,9 @@ class ClassVisitor extends Visitor { this.visitType(node.typeParameters); // then the usages this.visitType(node.superTypeArguments); - node.implements.forEach(imp => this.visitType(imp)); + node.implements.forEach(imp => { + this.visitType(imp); + }); this.visit(node.body); @@ -218,7 +222,9 @@ class ClassVisitor extends Visitor { { processRightHandNodes: true }, ); this.visitFunctionParameterTypeAnnotation(param, withMethodDecorators); - param.decorators.forEach(d => this.visit(d)); + param.decorators.forEach(d => { + this.visit(d); + }); } this.visitMetadataType(node.returnType, withMethodDecorators); @@ -260,7 +266,9 @@ class ClassVisitor extends Visitor { } } - node.decorators.forEach(d => this.#referencer.visit(d)); + node.decorators.forEach(d => { + this.#referencer.visit(d); + }); } protected visitMethod(node: TSESTree.MethodDefinition): void { @@ -274,7 +282,9 @@ class ClassVisitor extends Visitor { this.#referencer.visit(node.value); } - node.decorators.forEach(d => this.#referencer.visit(d)); + node.decorators.forEach(d => { + this.#referencer.visit(d); + }); } protected visitType(node: TSESTree.Node | null | undefined): void { @@ -378,7 +388,9 @@ class ClassVisitor extends Visitor { protected StaticBlock(node: TSESTree.StaticBlock): void { this.#referencer.scopeManager.nestClassStaticBlockScope(node); - node.body.forEach(b => this.visit(b)); + node.body.forEach(b => { + this.visit(b); + }); this.#referencer.close(node); } diff --git a/packages/scope-manager/src/referencer/Referencer.ts b/packages/scope-manager/src/referencer/Referencer.ts index 6082f4846611..e8ad0c26ab8d 100644 --- a/packages/scope-manager/src/referencer/Referencer.ts +++ b/packages/scope-manager/src/referencer/Referencer.ts @@ -270,7 +270,9 @@ class Referencer extends Visitor { { processRightHandNodes: true }, ); this.visitFunctionParameterTypeAnnotation(param); - param.decorators.forEach(d => this.visit(d)); + param.decorators.forEach(d => { + this.visit(d); + }); } this.visitType(node.returnType); diff --git a/packages/scope-manager/src/scope/ScopeBase.ts b/packages/scope-manager/src/scope/ScopeBase.ts index 1cdb2c98586c..6cd33f93fa80 100644 --- a/packages/scope-manager/src/scope/ScopeBase.ts +++ b/packages/scope-manager/src/scope/ScopeBase.ts @@ -365,7 +365,9 @@ abstract class ScopeBase< // Try Resolving all references in this scope. assert(this.leftToResolve); - this.leftToResolve.forEach(ref => closeRef(ref, scopeManager)); + this.leftToResolve.forEach(ref => { + closeRef(ref, scopeManager); + }); this.leftToResolve = null; return this.upper; diff --git a/packages/scope-manager/src/scope/WithScope.ts b/packages/scope-manager/src/scope/WithScope.ts index 7058ab70faa5..9ab1a377697b 100644 --- a/packages/scope-manager/src/scope/WithScope.ts +++ b/packages/scope-manager/src/scope/WithScope.ts @@ -23,7 +23,9 @@ class WithScope extends ScopeBase< return super.close(scopeManager); } assert(this.leftToResolve); - this.leftToResolve.forEach(ref => this.delegateToUpperScope(ref)); + this.leftToResolve.forEach(ref => { + this.delegateToUpperScope(ref); + }); this.leftToResolve = null; return this.upper; } diff --git a/packages/scope-manager/tests/eslint-scope/references.test.ts b/packages/scope-manager/tests/eslint-scope/references.test.ts index c7973556f269..db75364ee1ce 100644 --- a/packages/scope-manager/tests/eslint-scope/references.test.ts +++ b/packages/scope-manager/tests/eslint-scope/references.test.ts @@ -447,7 +447,7 @@ describe('References:', () => { 'new function({b: a = 0} = {}) {}', ]; - trueCodes.forEach(code => + trueCodes.forEach(code => { it(`"${code}", all references should be true.`, () => { const { scopeManager } = parseAndAnalyze(code); @@ -464,8 +464,8 @@ describe('References:', () => { expect(reference.isWrite()).toBeTruthy(); expect(reference.init).toBeTruthy(); }); - }), - ); + }); + }); let falseCodes = [ 'let a; a = 0;', @@ -481,7 +481,7 @@ describe('References:', () => { 'let a; for ({a = 0} in []);', ]; - falseCodes.forEach(code => + falseCodes.forEach(code => { it(`"${code}", all references should be false.`, () => { const { scopeManager } = parseAndAnalyze(code); @@ -498,8 +498,8 @@ describe('References:', () => { expect(reference.isWrite()).toBeTruthy(); expect(reference.init).toBeFalsy(); }); - }), - ); + }); + }); falseCodes = [ 'let a; let b = a;', @@ -517,7 +517,7 @@ describe('References:', () => { 'let a; a.foo = 0;', 'let a,b; b = a.foo;', ]; - falseCodes.forEach(code => + falseCodes.forEach(code => { it(`"${code}", readonly references of "a" should be undefined.`, () => { const { scopeManager } = parseAndAnalyze(code); @@ -537,8 +537,8 @@ describe('References:', () => { expect(reference.isRead()).toBeTruthy(); expect(reference.init).toBeUndefined(); }); - }), - ); + }); + }); }); describe('When emitDecoratorMetadata is true', () => { diff --git a/packages/scope-manager/tests/fixtures.test.ts b/packages/scope-manager/tests/fixtures.test.ts index 94510960bd97..6e28ae8f219b 100644 --- a/packages/scope-manager/tests/fixtures.test.ts +++ b/packages/scope-manager/tests/fixtures.test.ts @@ -172,7 +172,9 @@ function nestDescribe( } } -fixtures.forEach(f => nestDescribe(f)); +fixtures.forEach(f => { + nestDescribe(f); +}); if (ONLY === '') { // ensure that the snapshots are cleaned up, because jest-specific-snapshot won't do this check diff --git a/packages/type-utils/tests/isTypeReadonly.test.ts b/packages/type-utils/tests/isTypeReadonly.test.ts index 2adfaaec7aa8..c88970dc8975 100644 --- a/packages/type-utils/tests/isTypeReadonly.test.ts +++ b/packages/type-utils/tests/isTypeReadonly.test.ts @@ -139,13 +139,15 @@ describe('isTypeReadonly', () => { describe('is readonly circular', () => { const runTests = runTestIsReadonly; - it('handles circular readonly PropertySignature inside a readonly IndexSignature', () => - runTests('interface Test { readonly [key: string]: Test };')); + it('handles circular readonly PropertySignature inside a readonly IndexSignature', () => { + runTests('interface Test { readonly [key: string]: Test };'); + }); - it('handles circular readonly PropertySignature inside interdependent objects', () => + it('handles circular readonly PropertySignature inside interdependent objects', () => { runTests( 'interface Test1 { readonly [key: string]: Test } interface Test { readonly [key: string]: Test1 }', - )); + ); + }); }); describe('is not readonly', () => { @@ -163,8 +165,9 @@ describe('isTypeReadonly', () => { describe('is not readonly circular', () => { const runTests = runTestIsNotReadonly; - it('handles circular mutable PropertySignature', () => - runTests('interface Test { [key: string]: Test };')); + it('handles circular mutable PropertySignature', () => { + runTests('interface Test { [key: string]: Test };'); + }); it.each([ [ diff --git a/packages/types/tools/copy-ast-spec.ts b/packages/types/tools/copy-ast-spec.ts index fe5412061c8e..66c008191f0f 100644 --- a/packages/types/tools/copy-ast-spec.ts +++ b/packages/types/tools/copy-ast-spec.ts @@ -19,9 +19,15 @@ async function execAsync( stdio: 'inherit', }); - child.on('error', e => reject(e)); - child.on('exit', () => resolve()); - child.on('close', () => resolve()); + child.on('error', e => { + reject(e); + }); + child.on('exit', () => { + resolve(); + }); + child.on('close', () => { + resolve(); + }); }); } diff --git a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts b/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts index 21178000ee5e..f206371ecebf 100644 --- a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts +++ b/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts @@ -146,9 +146,9 @@ function getWatchProgramsForProjects( fileWatchCallbacks && fileWatchCallbacks.size > 0 ) { - fileWatchCallbacks.forEach(cb => - cb(filePath, ts.FileWatcherEventKind.Changed), - ); + fileWatchCallbacks.forEach(cb => { + cb(filePath, ts.FileWatcherEventKind.Changed); + }); } const currentProjectsFromSettings = new Set(parseSettings.projects); @@ -400,9 +400,9 @@ function maybeInvalidateProgram( * We need to make sure typescript knows this so it can update appropriately */ log('tsconfig has changed - triggering program update. %s', tsconfigPath); - fileWatchCallbackTrackingMap - .get(tsconfigPath)! - .forEach(cb => cb(tsconfigPath, ts.FileWatcherEventKind.Changed)); + fileWatchCallbackTrackingMap.get(tsconfigPath)!.forEach(cb => { + cb(tsconfigPath, ts.FileWatcherEventKind.Changed); + }); // tsconfig change means that the file list more than likely changed, so clear the cache programFileListCache.delete(tsconfigPath); @@ -487,9 +487,9 @@ function maybeInvalidateProgram( } log('Marking file as deleted. %s', deletedFile); - fileWatchCallbacks.forEach(cb => - cb(deletedFile, ts.FileWatcherEventKind.Deleted), - ); + fileWatchCallbacks.forEach(cb => { + cb(deletedFile, ts.FileWatcherEventKind.Deleted); + }); // deleted files means that the file list _has_ changed, so clear the cache programFileListCache.delete(tsconfigPath); diff --git a/packages/typescript-estree/tests/lib/persistentParse.test.ts b/packages/typescript-estree/tests/lib/persistentParse.test.ts index 710b9c54ab5a..5c601a842a34 100644 --- a/packages/typescript-estree/tests/lib/persistentParse.test.ts +++ b/packages/typescript-estree/tests/lib/persistentParse.test.ts @@ -23,7 +23,9 @@ afterEach(() => { clearWatchCaches(); // clean up the temporary files and folders - tmpDirs.forEach(t => t.removeCallback()); + tmpDirs.forEach(t => { + t.removeCallback(); + }); tmpDirs.clear(); // restore original cwd @@ -95,31 +97,47 @@ function baseTests( it('parses both files successfully when included', () => { const PROJECT_DIR = setup(tsConfigIncludeAll); - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).not.toThrow(); }); it('parses included files, and throws on excluded files', () => { const PROJECT_DIR = setup(tsConfigExcludeBar); - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR)).toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).toThrow(); }); it('allows parsing of new files', () => { const PROJECT_DIR = setup(tsConfigIncludeAll, false); // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); // bar should throw because it doesn't exist yet - expect(() => parseFile('bar', PROJECT_DIR)).toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).toThrow(); // write a new file and attempt to parse it writeFile(PROJECT_DIR, 'bar'); // both files should parse fine now - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).not.toThrow(); }); it('allows parsing of deeply nested new files', () => { @@ -127,22 +145,32 @@ function baseTests( const bazSlashBar = 'baz/bar' as const; // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); // bar should throw because it doesn't exist yet - expect(() => parseFile(bazSlashBar, PROJECT_DIR)).toThrow(); + expect(() => { + parseFile(bazSlashBar, PROJECT_DIR); + }).toThrow(); // write a new file and attempt to parse it writeFile(PROJECT_DIR, bazSlashBar); // both files should parse fine now - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile(bazSlashBar, PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile(bazSlashBar, PROJECT_DIR); + }).not.toThrow(); }); it('allows parsing of deeply nested new files in new folder', () => { const PROJECT_DIR = setup(tsConfigIncludeAll); - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); // Create deep folder structure after first parse (this is important step) // context: https://github.com/typescript-eslint/typescript-eslint/issues/1394 @@ -154,7 +182,9 @@ function baseTests( // write a new file and attempt to parse it writeFile(PROJECT_DIR, bazSlashBar); - expect(() => parseFile(bazSlashBar, PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile(bazSlashBar, PROJECT_DIR); + }).not.toThrow(); }); it('allows renaming of files', () => { @@ -162,40 +192,60 @@ function baseTests( const bazSlashBar = 'baz/bar' as const; // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); // bar should throw because it doesn't exist yet - expect(() => parseFile(bazSlashBar, PROJECT_DIR)).toThrow(); + expect(() => { + parseFile(bazSlashBar, PROJECT_DIR); + }).toThrow(); // write a new file and attempt to parse it renameFile(PROJECT_DIR, 'bar', bazSlashBar); // both files should parse fine now - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile(bazSlashBar, PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile(bazSlashBar, PROJECT_DIR); + }).not.toThrow(); }); it('reacts to changes in the tsconfig', () => { const PROJECT_DIR = setup(tsConfigExcludeBar); // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR)).toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).toThrow(); // change the config file so it now includes all files writeTSConfig(PROJECT_DIR, tsConfigIncludeAll); clearCaches(); - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).not.toThrow(); }); it('should work with relative paths', () => { const PROJECT_DIR = setup(tsConfigIncludeAll, false); // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR, true)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR, true); + }).not.toThrow(); // bar should throw because it doesn't exist yet - expect(() => parseFile('bar', PROJECT_DIR, true)).toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR, true); + }).toThrow(); // write a new file and attempt to parse it writeFile(PROJECT_DIR, 'bar'); @@ -204,8 +254,12 @@ function baseTests( expect(existsSync('bar', PROJECT_DIR)).toBe(true); // both files should parse fine now - expect(() => parseFile('foo', PROJECT_DIR, true)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR, true)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR, true); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR, true); + }).not.toThrow(); }); it('should work with relative paths without tsconfig root', () => { @@ -213,9 +267,13 @@ function baseTests( process.chdir(PROJECT_DIR); // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR, true, true)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR, true, true); + }).not.toThrow(); // bar should throw because it doesn't exist yet - expect(() => parseFile('bar', PROJECT_DIR, true, true)).toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR, true, true); + }).toThrow(); // write a new file and attempt to parse it writeFile(PROJECT_DIR, 'bar'); @@ -225,8 +283,12 @@ function baseTests( expect(existsSync('bar', PROJECT_DIR)).toBe(true); // both files should parse fine now - expect(() => parseFile('foo', PROJECT_DIR, true, true)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR, true, true)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR, true, true); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR, true, true); + }).not.toThrow(); }); } @@ -278,15 +340,23 @@ describe('persistent parse', () => { const PROJECT_DIR = setup({}, false); // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR)).toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).toThrow(); // write a new file and attempt to parse it writeFile(PROJECT_DIR, 'bar'); clearCaches(); - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile('bar', PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile('bar', PROJECT_DIR); + }).not.toThrow(); }); it('handles tsconfigs with no includes/excludes (nested)', () => { @@ -294,15 +364,23 @@ describe('persistent parse', () => { const bazSlashBar = 'baz/bar' as const; // parse once to: assert the config as correct, and to make sure the program is setup - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile(bazSlashBar, PROJECT_DIR)).toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile(bazSlashBar, PROJECT_DIR); + }).toThrow(); // write a new file and attempt to parse it writeFile(PROJECT_DIR, bazSlashBar); clearCaches(); - expect(() => parseFile('foo', PROJECT_DIR)).not.toThrow(); - expect(() => parseFile(bazSlashBar, PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile('foo', PROJECT_DIR); + }).not.toThrow(); + expect(() => { + parseFile(bazSlashBar, PROJECT_DIR); + }).not.toThrow(); }); }); } @@ -346,7 +424,9 @@ describe('persistent parse', () => { it(`first parse of ${name} should not throw`, () => { const PROJECT_DIR = setup(tsConfigIncludeAll); writeFile(PROJECT_DIR, name); - expect(() => parseFile(name, PROJECT_DIR)).not.toThrow(); + expect(() => { + parseFile(name, PROJECT_DIR); + }).not.toThrow(); }); } }); diff --git a/packages/typescript-estree/tests/lib/semanticInfo.test.ts b/packages/typescript-estree/tests/lib/semanticInfo.test.ts index f5f78934a880..8e0e00dc5309 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo.test.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo.test.ts @@ -37,7 +37,9 @@ function createOptions(fileName: string): TSESTreeOptions & { cwd?: string } { } // ensure tsconfig-parser watch caches are clean for each test -beforeEach(() => clearCaches()); +beforeEach(() => { + clearCaches(); +}); describe('semanticInfo', () => { // test all AST snapshots diff --git a/packages/website/src/components/OptionsSelector.tsx b/packages/website/src/components/OptionsSelector.tsx index b881319e58ab..bc3b2febec1e 100644 --- a/packages/website/src/components/OptionsSelector.tsx +++ b/packages/website/src/components/OptionsSelector.tsx @@ -56,7 +56,9 @@ function OptionsSelectorContent({ className="text--right" value={state.ts} disabled={!tsVersions.length} - onChange={(ts): void => setState({ ts })} + onChange={(ts): void => { + setState({ ts }); + }} options={tsVersions.length ? tsVersions : [state.ts]} /> @@ -68,7 +70,9 @@ function OptionsSelectorContent({ setState({ fileType })} + onChange={(fileType): void => { + setState({ fileType }); + }} options={fileTypes} /> @@ -76,7 +80,9 @@ function OptionsSelectorContent({ setState({ sourceType })} + onChange={(sourceType): void => { + setState({ sourceType }); + }} options={['script', 'module']} /> @@ -84,14 +90,18 @@ function OptionsSelectorContent({ setState({ scroll })} + onChange={(scroll): void => { + setState({ scroll }); + }} /> setState({ showTokens })} + onChange={(showTokens): void => { + setState({ showTokens }); + }} /> diff --git a/packages/website/src/components/Playground.tsx b/packages/website/src/components/Playground.tsx index ac06e4652ee4..a717d84fa035 100644 --- a/packages/website/src/components/Playground.tsx +++ b/packages/website/src/components/Playground.tsx @@ -174,7 +174,9 @@ function Playground(): React.JSX.Element { setState({ showAST: v })} + change={(v): void => { + setState({ showAST: v }); + }} /> {state.showAST === 'es' && ( void; mode: FilterMode; }): React.JSX.Element { - const toNextMode = (): void => + const toNextMode = (): void => { setMode(filterModes[(filterModes.indexOf(mode) + 1) % filterModes.length]); + }; return (
  • diff --git a/packages/website/src/components/lib/createEventsBinder.ts b/packages/website/src/components/lib/createEventsBinder.ts index 6b5bfaecbee1..47cc37fd3d17 100644 --- a/packages/website/src/components/lib/createEventsBinder.ts +++ b/packages/website/src/components/lib/createEventsBinder.ts @@ -7,7 +7,9 @@ export function createEventsBinder void>(): { return { trigger(...args: Parameters): void { - events.forEach(cb => cb(...args)); + events.forEach(cb => { + cb(...args); + }); }, register(cb: T): () => void { events.add(cb); diff --git a/packages/website/src/components/linter/bridge.ts b/packages/website/src/components/linter/bridge.ts index 4a4d52e44637..03ffb58e33aa 100644 --- a/packages/website/src/components/linter/bridge.ts +++ b/packages/website/src/components/linter/bridge.ts @@ -48,7 +48,9 @@ export function createFileSystem( ): void => { fileWatcherCallbacks.forEach((callbacks, key) => { if (key.test(path)) { - callbacks.forEach(cb => cb(path, type)); + callbacks.forEach(cb => { + cb(path, type); + }); } }); }; diff --git a/packages/website/src/components/typeDetails/SimplifiedTreeView.tsx b/packages/website/src/components/typeDetails/SimplifiedTreeView.tsx index c5dc1b37926d..3208d85cac17 100644 --- a/packages/website/src/components/typeDetails/SimplifiedTreeView.tsx +++ b/packages/website/src/components/typeDetails/SimplifiedTreeView.tsx @@ -32,7 +32,8 @@ function SimplifiedItem({ const onHover = useCallback( (v: boolean) => { if (isTSNode(value) && onHoverNode) { - return onHoverNode(v ? getRange(value, 'tsNode') : undefined); + onHoverNode(v ? getRange(value, 'tsNode') : undefined); + return; } }, [onHoverNode, value], diff --git a/packages/website/src/hooks/useBool.ts b/packages/website/src/hooks/useBool.ts index b06c9c40e5a4..c4e6c569e8da 100644 --- a/packages/website/src/hooks/useBool.ts +++ b/packages/website/src/hooks/useBool.ts @@ -6,10 +6,9 @@ export function useBool( ): [boolean, () => void, Dispatch>] { const [value, setValue] = useState(initialState); - const toggle = useCallback( - (): void => setValue(currentValue => !currentValue), - [], - ); + const toggle = useCallback((): void => { + setValue(currentValue => !currentValue); + }, []); return [value, toggle, setValue]; } diff --git a/packages/website/src/hooks/useMediaQuery.ts b/packages/website/src/hooks/useMediaQuery.ts index 1bd928c4a4b2..964797e20ddd 100644 --- a/packages/website/src/hooks/useMediaQuery.ts +++ b/packages/website/src/hooks/useMediaQuery.ts @@ -17,8 +17,9 @@ const useMediaQuery = (mediaQuery: string): boolean => { useEffect(() => { const mediaQueryList = window.matchMedia(mediaQuery); - const documentChangeHandler = (): void => + const documentChangeHandler = (): void => { setIsVerified(!!mediaQueryList.matches); + }; try { mediaQueryList.addEventListener('change', documentChangeHandler); diff --git a/packages/website/src/theme/CodeBlock/Content/String.tsx b/packages/website/src/theme/CodeBlock/Content/String.tsx index 6895cab853e2..906ebe3edca3 100644 --- a/packages/website/src/theme/CodeBlock/Content/String.tsx +++ b/packages/website/src/theme/CodeBlock/Content/String.tsx @@ -128,7 +128,9 @@ export default function CodeBlockString({ {(wordWrap.isEnabled || wordWrap.isCodeScrollable) && ( wordWrap.toggle()} + onClick={(): void => { + wordWrap.toggle(); + }} isEnabled={wordWrap.isEnabled} /> )}