From 167554fd5e884fabd8540a20a5da5163cfc4bce2 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 2 Dec 2023 19:20:57 -0500 Subject: [PATCH 1/5] chore: enable no-non-null-assertion internally, excluding tests --- .eslintrc.js | 2 +- .../src/rules/plugin-test-formatting.ts | 3 + .../eslint-plugin-tslint/src/rules/config.ts | 1 + .../eslint-plugin/src/rules/ban-ts-comment.ts | 1 + .../eslint-plugin/src/rules/block-spacing.ts | 1 + .../eslint-plugin/src/rules/brace-style.ts | 1 + .../eslint-plugin/src/rules/comma-spacing.ts | 1 + .../rules/consistent-generic-constructors.ts | 1 + .../src/rules/consistent-type-assertions.ts | 1 + .../src/rules/consistent-type-imports.ts | 1 + .../src/rules/enum-utils/shared.ts | 2 + .../rules/explicit-member-accessibility.ts | 2 + .../src/rules/func-call-spacing.ts | 1 + packages/eslint-plugin/src/rules/indent.ts | 1 + .../eslint-plugin/src/rules/key-spacing.ts | 1 + .../src/rules/keyword-spacing.ts | 1 + .../src/rules/lines-around-comment.ts | 1 + .../src/rules/member-ordering.ts | 1 + .../src/rules/no-confusing-void-expression.ts | 1 + .../src/rules/no-dynamic-delete.ts | 2 + .../src/rules/no-inferrable-types.ts | 1 + .../src/rules/no-invalid-void-type.ts | 1 + .../src/rules/no-loss-of-precision.ts | 3 +- .../eslint-plugin/src/rules/no-mixed-enums.ts | 1 + packages/eslint-plugin/src/rules/no-shadow.ts | 2 + .../eslint-plugin/src/rules/no-this-alias.ts | 3 +- .../eslint-plugin/src/rules/no-type-alias.ts | 2 + .../src/rules/no-unnecessary-condition.ts | 2 +- .../src/rules/no-unsafe-assignment.ts | 1 + .../src/rules/object-curly-spacing.ts | 1 + .../rules/padding-line-between-statements.ts | 1 + .../src/rules/parameter-properties.ts | 1 + .../src/rules/prefer-function-type.ts | 1 + .../src/rules/prefer-nullish-coalescing.ts | 2 + .../rules/prefer-readonly-parameter-types.ts | 1 + .../src/rules/prefer-readonly.ts | 1 + .../rules/prefer-string-starts-ends-with.ts | 1 + .../src/rules/promise-function-async.ts | 7 ++ .../src/rules/space-before-function-paren.ts | 1 + .../src/rules/space-infix-ops.ts | 1 + .../src/rules/strict-boolean-expressions.ts | 7 ++ .../src/rules/switch-exhaustiveness-check.ts | 2 + .../src/rules/type-annotation-spacing.ts | 4 + .../src/rules/unified-signatures.ts | 2 + .../src/util/collectUnusedVariables.ts | 6 ++ .../src/util/getWrappingFixer.ts | 4 + .../eslint-plugin/tests/rules/indent/utils.ts | 84 +------------------ .../tools/generate-breaking-changes.mts | 1 + .../eslint-plugin/tools/generate-configs.ts | 1 + packages/repo-tools/src/generate-lib.ts | 2 + packages/rule-tester/src/RuleTester.ts | 2 + .../rule-tester/src/utils/config-validator.ts | 2 + .../src/utils/validationHelpers.ts | 1 + packages/scope-manager/src/scope/ScopeBase.ts | 5 +- .../tests/util/getSpecificNode.ts | 1 + packages/type-utils/src/getTokenAtPosition.ts | 3 + packages/typescript-estree/src/convert.ts | 3 +- .../getWatchProgramsForProjects.ts | 2 + .../src/create-program/useProvidedPrograms.ts | 4 +- packages/typescript-estree/src/parser.ts | 3 +- .../src/useProgramFromProjectService.ts | 2 + .../components/config/ConfigTypeScript.tsx | 3 + .../src/components/editor/LoadedEditor.tsx | 3 + .../components/editor/useSandboxServices.ts | 1 + .../src/components/hooks/useHashState.ts | 1 + .../website/src/components/lib/jsonSchema.ts | 3 + .../src/components/lib/shallowEqual.ts | 1 + .../src/components/linter/createParser.ts | 1 + .../website/src/components/linter/utils.ts | 1 + packages/website/src/components/options.ts | 1 + .../theme/MDXComponents/RuleAttributes.tsx | 1 + 71 files changed, 124 insertions(+), 93 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 400ed10c4aaa..3aa4c2295c0b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -83,7 +83,6 @@ module.exports = { { allowIIFEs: true }, ], '@typescript-eslint/no-explicit-any': 'error', - '@typescript-eslint/no-non-null-assertion': 'off', 'no-constant-condition': 'off', '@typescript-eslint/no-unnecessary-condition': [ 'error', @@ -252,6 +251,7 @@ module.exports = { 'error', { allow: ['arrowFunctions'] }, ], + '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-call': 'off', '@typescript-eslint/no-unsafe-member-access': 'off', 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..acfd3813e064 100644 --- a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts +++ b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts @@ -56,6 +56,7 @@ function getExpectedIndentForNode( sourceCodeLines: string[], ): number { const lineIdx = node.loc.start.line - 1; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const indent = START_OF_LINE_WHITESPACE_MATCHER.exec( sourceCodeLines[lineIdx], )![1]; @@ -347,6 +348,7 @@ export default createRule({ // +2 because we expect the string contents are indented one level const expectedIndent = parentIndent + 2; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const firstLineIndent = START_OF_LINE_WHITESPACE_MATCHER.exec( lines[0], )![1]; @@ -369,6 +371,7 @@ export default createRule({ continue; } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const matches = START_OF_LINE_WHITESPACE_MATCHER.exec(line)!; const indent = matches[1]; diff --git a/packages/eslint-plugin-tslint/src/rules/config.ts b/packages/eslint-plugin-tslint/src/rules/config.ts index c9170531b501..98d3a8259edf 100644 --- a/packages/eslint-plugin-tslint/src/rules/config.ts +++ b/packages/eslint-plugin-tslint/src/rules/config.ts @@ -19,6 +19,7 @@ function memoize unknown>( const key = resolver(...(args as Parameters)); if (cache.has(key)) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return cache.get(key)!; } const result = func(...args); diff --git a/packages/eslint-plugin/src/rules/ban-ts-comment.ts b/packages/eslint-plugin/src/rules/ban-ts-comment.ts index 5c70c7b9179b..4273b3470093 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-comment.ts @@ -132,6 +132,7 @@ export default createRule<[Options], MessageIds>({ if (!match) { return; } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { directive, description } = match.groups!; const fullDirective = `ts-${directive}` as keyof Options; diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 8a4ed0a00da5..e5d80ec4c375 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/brace-style.ts b/packages/eslint-plugin/src/rules/brace-style.ts index 412065b91ff5..7581fbf176c9 100644 --- a/packages/eslint-plugin/src/rules/brace-style.ts +++ b/packages/eslint-plugin/src/rules/brace-style.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/comma-spacing.ts b/packages/eslint-plugin/src/rules/comma-spacing.ts index 851d6fcc19b0..1c05848241c0 100644 --- a/packages/eslint-plugin/src/rules/comma-spacing.ts +++ b/packages/eslint-plugin/src/rules/comma-spacing.ts @@ -71,6 +71,7 @@ export default createRule({ for (const element of node.elements) { let token: TSESTree.Token | null; if (element == null) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion token = sourceCode.getTokenAfter(previousToken!); if (token && isCommaToken(token)) { ignoredTokens.add(token); diff --git a/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts b/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts index 1913cdfc4e52..434054f9ad25 100644 --- a/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts +++ b/packages/eslint-plugin/src/rules/consistent-generic-constructors.ts @@ -95,6 +95,7 @@ export default createRule({ } // If the property's computed, we have to attach the // annotation after the square bracket, not the enclosed expression + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return sourceCode.getTokenAfter(node.key)!; } return [ diff --git a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts index ed3b0bf487a4..48034fbfe4b8 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/consistent-type-imports.ts b/packages/eslint-plugin/src/rules/consistent-type-imports.ts index fd452d750b66..4734485b651d 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-imports.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-imports.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { diff --git a/packages/eslint-plugin/src/rules/enum-utils/shared.ts b/packages/eslint-plugin/src/rules/enum-utils/shared.ts index b2a93b4f1162..6c1874d144f8 100644 --- a/packages/eslint-plugin/src/rules/enum-utils/shared.ts +++ b/packages/eslint-plugin/src/rules/enum-utils/shared.ts @@ -12,11 +12,13 @@ import { isTypeFlagSet } from '../../util'; * - `Fruit.Apple` --> `Fruit` */ function getBaseEnumType(typeChecker: ts.TypeChecker, type: ts.Type): ts.Type { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const symbol = type.getSymbol()!; if (!tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.EnumMember)) { return type; } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return typeChecker.getTypeAtLocation(symbol.valueDeclaration!.parent); } diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index 18919815cd19..ed85b6f6c3f1 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -209,6 +209,7 @@ export default createRule({ } } } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return fixer.removeRange(rangeToRemove!); }; } @@ -230,6 +231,7 @@ export default createRule({ ): TSESLint.RuleFix | null { if (node.decorators.length) { const lastDecorator = node.decorators[node.decorators.length - 1]; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const nextToken = sourceCode.getTokenAfter(lastDecorator)!; return fixer.insertTextBefore(nextToken, `${accessibility} `); } diff --git a/packages/eslint-plugin/src/rules/func-call-spacing.ts b/packages/eslint-plugin/src/rules/func-call-spacing.ts index a0645e640409..4d664fc4d031 100644 --- a/packages/eslint-plugin/src/rules/func-call-spacing.ts +++ b/packages/eslint-plugin/src/rules/func-call-spacing.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/indent.ts b/packages/eslint-plugin/src/rules/indent.ts index b50d6b71814a..1ddb5a7b9409 100644 --- a/packages/eslint-plugin/src/rules/indent.ts +++ b/packages/eslint-plugin/src/rules/indent.ts @@ -380,6 +380,7 @@ export default createRule({ TSMappedType(node: TSESTree.TSMappedType) { const sourceCode = getSourceCode(context); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const squareBracketStart = sourceCode.getTokenBefore( node.typeParameter, )!; diff --git a/packages/eslint-plugin/src/rules/key-spacing.ts b/packages/eslint-plugin/src/rules/key-spacing.ts index cfec69fdcbb5..4644a5139f79 100644 --- a/packages/eslint-plugin/src/rules/key-spacing.ts +++ b/packages/eslint-plugin/src/rules/key-spacing.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/keyword-spacing.ts b/packages/eslint-plugin/src/rules/keyword-spacing.ts index 0e4e26b4fa49..aab43c7a006c 100644 --- a/packages/eslint-plugin/src/rules/keyword-spacing.ts +++ b/packages/eslint-plugin/src/rules/keyword-spacing.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/lines-around-comment.ts b/packages/eslint-plugin/src/rules/lines-around-comment.ts index 548c39768b3c..19a03813de75 100644 --- a/packages/eslint-plugin/src/rules/lines-around-comment.ts +++ b/packages/eslint-plugin/src/rules/lines-around-comment.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index 95d6c3715e0f..cbc7a1c9c0e6 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { JSONSchema, TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; 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..c3807b4bedcb 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/no-dynamic-delete.ts b/packages/eslint-plugin/src/rules/no-dynamic-delete.ts index 5d99e32a149c..d2603300b9a6 100644 --- a/packages/eslint-plugin/src/rules/no-dynamic-delete.ts +++ b/packages/eslint-plugin/src/rules/no-dynamic-delete.ts @@ -70,8 +70,10 @@ export default createRule({ const sourceCode = getSourceCode(context); return [ + /* eslint-disable @typescript-eslint/no-non-null-assertion */ sourceCode.getTokenBefore(property)!.range[0], sourceCode.getTokenAfter(property)!.range[1], + /* eslint-enable @typescript-eslint/no-non-null-assertion */ ]; } }, diff --git a/packages/eslint-plugin/src/rules/no-inferrable-types.ts b/packages/eslint-plugin/src/rules/no-inferrable-types.ts index 122ff346a865..4abc0c7f1821 100644 --- a/packages/eslint-plugin/src/rules/no-inferrable-types.ts +++ b/packages/eslint-plugin/src/rules/no-inferrable-types.ts @@ -226,6 +226,7 @@ export default createRule({ node.left.optional) || (node.type === AST_NODE_TYPES.PropertyDefinition && node.definite) ) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion yield fixer.remove(sourceCode.getTokenBefore(typeNode)!); } yield fixer.remove(typeNode); diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index e9964edb9376..f45acb694582 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -207,6 +207,7 @@ export default createRule<[Options], MessageIds>({ // default cases if ( validParents.includes(node.parent.type) && + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion !invalidGrandParents.includes(node.parent.parent!.type) ) { return; diff --git a/packages/eslint-plugin/src/rules/no-loss-of-precision.ts b/packages/eslint-plugin/src/rules/no-loss-of-precision.ts index ed3747884abd..4d15c7ae643e 100644 --- a/packages/eslint-plugin/src/rules/no-loss-of-precision.ts +++ b/packages/eslint-plugin/src/rules/no-loss-of-precision.ts @@ -33,8 +33,7 @@ export default createRule({ ); } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const rules = baseRule!.create(context); + const rules = baseRule.create(context); function isSeparatedNumeric(node: TSESTree.Literal): boolean { return typeof node.value === 'number' && node.raw.includes('_'); diff --git a/packages/eslint-plugin/src/rules/no-mixed-enums.ts b/packages/eslint-plugin/src/rules/no-mixed-enums.ts index 2b79f31a67e6..4d78644e33d6 100644 --- a/packages/eslint-plugin/src/rules/no-mixed-enums.ts +++ b/packages/eslint-plugin/src/rules/no-mixed-enums.ts @@ -165,6 +165,7 @@ export default createRule({ // Merged namespaces must all exist in the same file. // We could instead compare this file's nodes to find the merges. const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node.id); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const declarations = typeChecker .getSymbolAtLocation(tsNode)! .getDeclarations()!; diff --git a/packages/eslint-plugin/src/rules/no-shadow.ts b/packages/eslint-plugin/src/rules/no-shadow.ts index c1e637962a5f..6804bcaba7a6 100644 --- a/packages/eslint-plugin/src/rules/no-shadow.ts +++ b/packages/eslint-plugin/src/rules/no-shadow.ts @@ -283,6 +283,7 @@ export default createRule({ * @returns Whether or not the variable name is allowed. */ function isAllowed(variable: TSESLint.Scope.Variable): boolean { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return options.allow!.includes(variable.name); } @@ -651,6 +652,7 @@ export default createRule({ const stack = globalScope.childScopes.slice(); while (stack.length) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const scope = stack.pop()!; stack.push(...scope.childScopes); diff --git a/packages/eslint-plugin/src/rules/no-this-alias.ts b/packages/eslint-plugin/src/rules/no-this-alias.ts index ece937cff3df..a75391c9effc 100644 --- a/packages/eslint-plugin/src/rules/no-this-alias.ts +++ b/packages/eslint-plugin/src/rules/no-this-alias.ts @@ -65,7 +65,8 @@ export default createRule({ const hasAllowedName = id.type === AST_NODE_TYPES.Identifier - ? allowedNames!.includes(id.name) + ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + allowedNames!.includes(id.name) : false; if (!hasAllowedName) { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-type-alias.ts b/packages/eslint-plugin/src/rules/no-type-alias.ts index b72c1f8b991a..85438af922d3 100644 --- a/packages/eslint-plugin/src/rules/no-type-alias.ts +++ b/packages/eslint-plugin/src/rules/no-type-alias.ts @@ -257,6 +257,7 @@ export default createRule({ type: TypeWithLabel, isTopLevel = false, ): void { + /* eslint-disable @typescript-eslint/no-non-null-assertion */ if (type.node.type === AST_NODE_TYPES.TSFunctionType) { // callback if (allowCallbacks === 'never') { @@ -309,6 +310,7 @@ export default createRule({ // unhandled type - shouldn't happen reportError(type.node, type.compositionType, isTopLevel, 'Unhandled'); } + /* eslint-enable @typescript-eslint/no-non-null-assertion */ } /** diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index a55fd0d3956a..f032634dbfda 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -436,7 +436,7 @@ export default createRule({ function checkCallExpression(node: TSESTree.CallExpression): void { // If this is something like arr.filter(x => /*condition*/), check `condition` if (isArrayPredicateFunction(node) && node.arguments.length) { - const callback = node.arguments[0]!; + const callback = node.arguments[0]; // Inline defined functions if ( callback.type === AST_NODE_TYPES.ArrowFunctionExpression || diff --git a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts index 4ce2f6db99a3..4ecb7d342225 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -342,6 +342,7 @@ export default createRule({ ): void { checkAssignment( node.key, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion node.value!, node, getComparisonType(node.typeAnnotation), diff --git a/packages/eslint-plugin/src/rules/object-curly-spacing.ts b/packages/eslint-plugin/src/rules/object-curly-spacing.ts index 66792ba75018..73d2f3074952 100644 --- a/packages/eslint-plugin/src/rules/object-curly-spacing.ts +++ b/packages/eslint-plugin/src/rules/object-curly-spacing.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/padding-line-between-statements.ts b/packages/eslint-plugin/src/rules/padding-line-between-statements.ts index 442c8135e072..4d8afc376d05 100644 --- a/packages/eslint-plugin/src/rules/padding-line-between-statements.ts +++ b/packages/eslint-plugin/src/rules/padding-line-between-statements.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/parameter-properties.ts b/packages/eslint-plugin/src/rules/parameter-properties.ts index 17fee949b01e..d7807bc031dc 100644 --- a/packages/eslint-plugin/src/rules/parameter-properties.ts +++ b/packages/eslint-plugin/src/rules/parameter-properties.ts @@ -177,6 +177,7 @@ export default createRule({ }, ':matches(ClassDeclaration, ClassExpression):exit'(): void { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const propertyNodesByName = propertyNodesByNameStack.pop()!; for (const [name, nodes] of propertyNodesByName) { diff --git a/packages/eslint-plugin/src/rules/prefer-function-type.ts b/packages/eslint-plugin/src/rules/prefer-function-type.ts index eecb8dc3ac4c..38c3b476226d 100644 --- a/packages/eslint-plugin/src/rules/prefer-function-type.ts +++ b/packages/eslint-plugin/src/rules/prefer-function-type.ts @@ -106,6 +106,7 @@ export default createRule({ : (fixer: TSESLint.RuleFixer): TSESLint.RuleFix[] => { const fixes: TSESLint.RuleFix[] = []; const start = member.range[0]; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const colonPos = member.returnType!.range[0] - start; const text = sourceCode.getText().slice(start, member.range[1]); const comments = sourceCode diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index be498cb94ad0..6fcaf2e44103 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -323,6 +323,7 @@ export default createRule({ return; } + /* eslint-disable @typescript-eslint/no-non-null-assertion */ const ignorableFlags = [ (ignorePrimitives === true || ignorePrimitives!.bigint) && ts.TypeFlags.BigInt, @@ -344,6 +345,7 @@ export default createRule({ ) { return; } + /* eslint-enable @typescript-eslint/no-non-null-assertion */ const barBarOperator = nullThrows( sourceCode.getTokenAfter( diff --git a/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts b/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts index 72b73a883520..7f6a4475fc9a 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts @@ -114,6 +114,7 @@ export default createRule({ const type = services.getTypeAtLocation(actualParam); const isReadOnly = isTypeReadonly(services.program, type, { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion treatMethodsAsReadonly: treatMethodsAsReadonly!, allow, }); diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index be92e541781c..04436476225b 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -184,6 +184,7 @@ export default createRule({ ); }, 'ClassDeclaration, ClassExpression:exit'(): void { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const finalizedClassScope = classScopeStack.pop()!; const sourceCode = getSourceCode(context); diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index 381d11529375..27e94dfc84b3 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -213,6 +213,7 @@ export default createRule({ function getPropertyRange( node: TSESTree.MemberExpression, ): [number, number] { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const dotOrOpenBracket = sourceCode.getTokenAfter( node.object, isNotClosingParenToken, diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 2c286cb45506..35365100e21f 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -95,6 +95,7 @@ export default createRule({ ) { const allAllowedPromiseNames = new Set([ 'Promise', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ...allowedPromiseNames!, ]); const services = getParserServices(context); @@ -116,6 +117,7 @@ export default createRule({ if ( !containsAllTypesByName( returnType, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion allowAny!, allAllowedPromiseNames, // If no return type is explicitly set, we check if any parts of the return type match a Promise (instead of requiring all to match). @@ -162,6 +164,7 @@ export default createRule({ const method = node.parent; // the token to put `async` before + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion let keyToken = sourceCode.getFirstToken(method)!; // if there are decorators then skip past them @@ -171,6 +174,7 @@ export default createRule({ ) { const lastDecorator = method.decorators[method.decorators.length - 1]; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion keyToken = sourceCode.getTokenAfter(lastDecorator)!; } @@ -179,11 +183,14 @@ export default createRule({ keyToken.type === AST_TOKEN_TYPES.Keyword && keyToken.range[0] < method.key.range[0] ) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion keyToken = sourceCode.getTokenAfter(keyToken)!; } // check if there is a space between key and previous token + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const insertSpace = !sourceCode.isSpaceBetween!( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion sourceCode.getTokenBefore(keyToken)!, keyToken, ); diff --git a/packages/eslint-plugin/src/rules/space-before-function-paren.ts b/packages/eslint-plugin/src/rules/space-before-function-paren.ts index 19836a9081f4..14b93f94c457 100644 --- a/packages/eslint-plugin/src/rules/space-before-function-paren.ts +++ b/packages/eslint-plugin/src/rules/space-before-function-paren.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/space-infix-ops.ts b/packages/eslint-plugin/src/rules/space-infix-ops.ts index 2bf643b08736..58b84a79d2b9 100644 --- a/packages/eslint-plugin/src/rules/space-infix-ops.ts +++ b/packages/eslint-plugin/src/rules/space-infix-ops.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { AST_TOKEN_TYPES, TSESTree } from '@typescript-eslint/utils'; import { getSourceCode } from '@typescript-eslint/utils/eslint-utils'; diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 7ead3c9367ad..df92c9f52e63 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -308,6 +308,7 @@ export default createRule({ // nullable boolean if (is('nullish', 'boolean')) { if (!options.allowNullableBoolean) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (isLogicalNegationExpression(node.parent!)) { // if (!nullableBoolean) context.report({ @@ -373,6 +374,7 @@ export default createRule({ // string if (is('string') || is('truthy string')) { if (!options.allowString) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (isLogicalNegationExpression(node.parent!)) { // if (!string) context.report({ @@ -448,6 +450,7 @@ export default createRule({ // nullable string if (is('nullish', 'string')) { if (!options.allowNullableString) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (isLogicalNegationExpression(node.parent!)) { // if (!nullableString) context.report({ @@ -547,6 +550,7 @@ export default createRule({ }), }); } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion } else if (isLogicalNegationExpression(node.parent!)) { // if (!number) context.report({ @@ -624,6 +628,7 @@ export default createRule({ // nullable number if (is('nullish', 'number')) { if (!options.allowNullableNumber) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (isLogicalNegationExpression(node.parent!)) { // if (!nullableNumber) context.report({ @@ -705,6 +710,7 @@ export default createRule({ // nullable object if (is('nullish', 'object')) { if (!options.allowNullableObject) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (isLogicalNegationExpression(node.parent!)) { // if (!nullableObject) context.report({ @@ -756,6 +762,7 @@ export default createRule({ is('nullish', 'number', 'string', 'enum') ) { if (!options.allowNullableEnum) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (isLogicalNegationExpression(node.parent!)) { context.report({ node, diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index 90172006589c..ef9e2edca654 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -125,10 +125,12 @@ export default createRule({ } // there were no existing cases + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const openingBrace = sourceCode.getTokenAfter( node.discriminant, isOpeningBraceToken, )!; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const closingBrace = sourceCode.getTokenAfter( node.discriminant, isClosingBraceToken, diff --git a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts index 442dd71162a2..606a94bfc267 100644 --- a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts +++ b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts @@ -167,8 +167,10 @@ export default createRule({ typeAnnotation: TSESTree.TypeNode, ): void { const nextToken = typeAnnotation; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const punctuatorTokenEnd = sourceCode.getTokenBefore(nextToken)!; let punctuatorTokenStart = punctuatorTokenEnd; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion let previousToken = sourceCode.getTokenBefore(punctuatorTokenEnd)!; let type = punctuatorTokenEnd.value; @@ -202,12 +204,14 @@ export default createRule({ // shift the start to the ? type = '?:'; punctuatorTokenStart = previousToken; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion previousToken = sourceCode.getTokenBefore(previousToken)!; // handle the +/- modifiers for optional modification operators if (previousToken.value === '+' || previousToken.value === '-') { type = `${previousToken.value}?:`; punctuatorTokenStart = previousToken; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion previousToken = sourceCode.getTokenBefore(previousToken)!; } } diff --git a/packages/eslint-plugin/src/rules/unified-signatures.ts b/packages/eslint-plugin/src/rules/unified-signatures.ts index 0d4b8e8035d3..7d4aecb87fd1 100644 --- a/packages/eslint-plugin/src/rules/unified-signatures.ts +++ b/packages/eslint-plugin/src/rules/unified-signatures.ts @@ -508,8 +508,10 @@ export default createRule({ function checkScope(): void { const failures = checkOverloads( + /* eslint-disable @typescript-eslint/no-non-null-assertion */ Array.from(currentScope!.overloads.values()), currentScope!.typeParameters, + /* eslint-enable @typescript-eslint/no-non-null-assertion */ ); addFailures(failures); currentScope = scopes.pop(); diff --git a/packages/eslint-plugin/src/util/collectUnusedVariables.ts b/packages/eslint-plugin/src/util/collectUnusedVariables.ts index 81184ec2a08a..a24192d9d20d 100644 --- a/packages/eslint-plugin/src/util/collectUnusedVariables.ts +++ b/packages/eslint-plugin/src/util/collectUnusedVariables.ts @@ -137,6 +137,7 @@ class UnusedVarsVisitor< let node: TSESTree.Node; if (typeof variableOrIdentifierOrName === 'string') { name = variableOrIdentifierOrName; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion node = parent!; } else { name = variableOrIdentifierOrName.name; @@ -431,11 +432,13 @@ function isExported(variable: TSESLint.Scope.Variable): boolean { let node = definition.node; if (node.type === AST_NODE_TYPES.VariableDeclarator) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion node = node.parent!; } else if (definition.type === TSESLint.Scope.DefinitionType.Parameter) { return false; } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return node.parent!.type.indexOf('Export') === 0; }); } @@ -565,8 +568,10 @@ function isUsedVariable(variable: TSESLint.Scope.Variable): boolean { const id = ref.identifier; const parent = id.parent; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const grandparent = parent.parent!; const refScope = ref.from.variableScope; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const varScope = ref.resolved!.scope.variableScope; const canBeUsedLater = refScope !== varScope || isInLoop(id); @@ -698,6 +703,7 @@ function isUsedVariable(variable: TSESLint.Scope.Variable): boolean { const id = ref.identifier; const parent = id.parent; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const grandparent = parent.parent!; return ( diff --git a/packages/eslint-plugin/src/util/getWrappingFixer.ts b/packages/eslint-plugin/src/util/getWrappingFixer.ts index 043d144ec5cb..685c7c44f420 100644 --- a/packages/eslint-plugin/src/util/getWrappingFixer.ts +++ b/packages/eslint-plugin/src/util/getWrappingFixer.ts @@ -94,6 +94,7 @@ export function isStrongPrecedenceNode(innerNode: TSESTree.Node): boolean { * Check if a node's parent could have different precedence if the node changes. */ function isWeakPrecedenceParent(node: TSESTree.Node): boolean { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const parent = node.parent!; if ( @@ -141,6 +142,7 @@ function isMissingSemicolonBefore( sourceCode: TSESLint.SourceCode, ): boolean { for (;;) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const parent = node.parent!; if (parent.type === AST_NODE_TYPES.ExpressionStatement) { @@ -154,6 +156,7 @@ function isMissingSemicolonBefore( const previousStatement = block.body[statementIndex - 1]; if ( statementIndex > 0 && + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion sourceCode.getLastToken(previousStatement)!.value !== ';' ) { return true; @@ -173,6 +176,7 @@ function isMissingSemicolonBefore( * Checks if a node is LHS of an operator. */ function isLeftHandSide(node: TSESTree.Node): boolean { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const parent = node.parent!; // a++ diff --git a/packages/eslint-plugin/tests/rules/indent/utils.ts b/packages/eslint-plugin/tests/rules/indent/utils.ts index ae0b6e502ed0..19a108063dbf 100644 --- a/packages/eslint-plugin/tests/rules/indent/utils.ts +++ b/packages/eslint-plugin/tests/rules/indent/utils.ts @@ -1,17 +1,6 @@ // The following code is adapted from the the code in eslint. // License: https://github.com/eslint/eslint/blob/48700fc8408f394887cdedd071b22b757700fdcb/LICENSE -import type { - AST_NODE_TYPES, - AST_TOKEN_TYPES, - TSESLint, -} from '@typescript-eslint/utils'; - -import type rule from '../../../src/rules/indent'; -import type { InferMessageIdsTypeFromRule } from '../../../src/util'; - -type MessageIds = InferMessageIdsTypeFromRule; - /** * Prevents leading spaces in a multiline template literal from appearing in the resulting string * @param strings The strings in the template literal @@ -26,80 +15,9 @@ export function unIndent(strings: TemplateStringsArray): string { .split('\n'); const lineIndents = lines .filter(line => line.trim()) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion .map(line => WHITESPACE_REGEX.exec(line)![0].length); const minLineIndent = Math.min(...lineIndents); return lines.map(line => line.slice(minLineIndent)).join('\n'); } - -type ProvidedError = [ - // line number - number, - // expected indent - number | string, - // actual indent - number | string, - // node type - AST_NODE_TYPES | AST_TOKEN_TYPES, -]; - -function is2DProvidedErrorArr( - providedErrors?: ProvidedError | ProvidedError[], -): providedErrors is ProvidedError[] { - return !!providedErrors && Array.isArray(providedErrors[0]); -} - -/** - * Create error message object for failure cases with a single 'found' indentation type - * @param providedErrors error info - * @returns returns the error messages collection - */ -export function expectedErrors( - providedErrors: ProvidedError | ProvidedError[], -): TSESLint.TestCaseError[]; -/** - * Create error message object for failure cases with a single 'found' indentation type - * @param providedIndentType indent type of string or tab - * @param providedErrors error info - * @returns returns the error messages collection - */ -export function expectedErrors( - providedIndentType: string, - providedErrors: ProvidedError | ProvidedError[], -): TSESLint.TestCaseError[]; -export function expectedErrors( - providedIndentType: ProvidedError | ProvidedError[] | string, - providedErrors?: ProvidedError | ProvidedError[], -): TSESLint.TestCaseError[] { - let indentType: string; - let errors: ProvidedError[]; - - if (Array.isArray(providedIndentType)) { - errors = is2DProvidedErrorArr(providedIndentType) - ? providedIndentType - : [providedIndentType]; - indentType = 'space'; - } else { - errors = is2DProvidedErrorArr(providedErrors) - ? providedErrors - : [providedErrors!]; - indentType = providedIndentType; - } - - return errors.map(err => { - const [line, expected, actual, type] = err; - - return { - messageId: 'wrongIndentation', - data: { - expected: - typeof expected === 'string' && typeof actual === 'string' - ? expected - : `${expected} ${indentType}${expected === 1 ? '' : 's'}`, - actual, - }, - type, - line, - }; - }); -} diff --git a/packages/eslint-plugin/tools/generate-breaking-changes.mts b/packages/eslint-plugin/tools/generate-breaking-changes.mts index 05f4d8d5485a..c983351be553 100644 --- a/packages/eslint-plugin/tools/generate-breaking-changes.mts +++ b/packages/eslint-plugin/tools/generate-breaking-changes.mts @@ -131,6 +131,7 @@ async function main(): Promise { ...Object.entries(rules).map(([ruleName, { meta }]) => { const { deprecated } = meta; const { extendsBaseRule, recommended, requiresTypeChecking } = + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion meta.docs!; return [ diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index fb60d86449b9..9f70d4095af4 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -125,6 +125,7 @@ async function main(): Promise { settings.baseRuleForExtensionRule !== 'exclude' && BASE_RULES_TO_BE_OVERRIDDEN.has(key) ) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const baseRuleName = BASE_RULES_TO_BE_OVERRIDDEN.get(key)!; console.log( baseRuleName diff --git a/packages/repo-tools/src/generate-lib.ts b/packages/repo-tools/src/generate-lib.ts index c9a0a722a02c..6fae4166ce65 100644 --- a/packages/repo-tools/src/generate-lib.ts +++ b/packages/repo-tools/src/generate-lib.ts @@ -105,6 +105,7 @@ function sanitize(name: string): string { } function getVariablesFromScope(scopeManager: ScopeManager): Variable[] { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const scope = scopeManager.globalScope!.childScopes[0]; const variables: Variable[] = []; for (const variable of scope.variables) { @@ -120,6 +121,7 @@ const REFERENCE_REGEX = /\/ /; function getReferences( ast: TSESTree.Program & { comments?: TSESTree.Comment[] }, ): Set { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const comments = ast.comments!.filter( c => c.type === AST_TOKEN_TYPES.Line && diff --git a/packages/rule-tester/src/RuleTester.ts b/packages/rule-tester/src/RuleTester.ts index ad28d93a1478..681cde44cdc5 100644 --- a/packages/rule-tester/src/RuleTester.ts +++ b/packages/rule-tester/src/RuleTester.ts @@ -615,8 +615,10 @@ export class RuleTester extends TestFramework { messages, output, // is definitely assigned within the `rule-tester/validate-ast` rule + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion beforeAST: beforeAST!, // is definitely assigned within the `rule-tester/validate-ast` rule + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion afterAST: cloneDeeplyExcludesParent(afterAST!), }; } diff --git a/packages/rule-tester/src/utils/config-validator.ts b/packages/rule-tester/src/utils/config-validator.ts index d3690bc9ba17..75dee945cbde 100644 --- a/packages/rule-tester/src/utils/config-validator.ts +++ b/packages/rule-tester/src/utils/config-validator.ts @@ -172,6 +172,7 @@ function validateRules( return; } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion validateRuleOptions(rule, id, rulesConfig[id]!, source); }); } @@ -255,6 +256,7 @@ function validateConfigSchema( if (!validateSchema(config)) { throw new Error( `ESLint configuration in ${source} is invalid:\n${formatErrors( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion validateSchema.errors!, )}`, ); diff --git a/packages/rule-tester/src/utils/validationHelpers.ts b/packages/rule-tester/src/utils/validationHelpers.ts index 34e0ca3277de..34b0bac1b4dd 100644 --- a/packages/rule-tester/src/utils/validationHelpers.ts +++ b/packages/rule-tester/src/utils/validationHelpers.ts @@ -64,6 +64,7 @@ export function sanitize(text: string): string { return text.replace( // eslint-disable-next-line no-control-regex /[\u0000-\u0009\u000b-\u001a]/gu, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion c => `\\u${c.codePointAt(0)!.toString(16).padStart(4, '0')}`, ); } diff --git a/packages/scope-manager/src/scope/ScopeBase.ts b/packages/scope-manager/src/scope/ScopeBase.ts index 1cdb2c98586c..ff33d74649de 100644 --- a/packages/scope-manager/src/scope/ScopeBase.ts +++ b/packages/scope-manager/src/scope/ScopeBase.ts @@ -240,7 +240,8 @@ abstract class ScopeBase< this.block = block; this.variableScope = this.isVariableScope() ? this - : upperScopeAsScopeBase!.variableScope; + : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + upperScopeAsScopeBase!.variableScope; this.upper = upperScope; /** @@ -337,8 +338,10 @@ abstract class ScopeBase< let current = this as Scope | null; do { + /* eslint-disable @typescript-eslint/no-non-null-assertion */ current!.through.push(ref); current = current!.upper; + /* eslint-enable @typescript-eslint/no-non-null-assertion */ } while (current); }; diff --git a/packages/scope-manager/tests/util/getSpecificNode.ts b/packages/scope-manager/tests/util/getSpecificNode.ts index 520d43bc7a86..42a98708f388 100644 --- a/packages/scope-manager/tests/util/getSpecificNode.ts +++ b/packages/scope-manager/tests/util/getSpecificNode.ts @@ -44,6 +44,7 @@ function getSpecificNode( // should have found at least one node expect(node).not.toBeFalsy(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return node!; } diff --git a/packages/type-utils/src/getTokenAtPosition.ts b/packages/type-utils/src/getTokenAtPosition.ts index 9307a9cf5c40..3244f4d4de19 100644 --- a/packages/type-utils/src/getTokenAtPosition.ts +++ b/packages/type-utils/src/getTokenAtPosition.ts @@ -7,6 +7,7 @@ export function getTokenAtPosition( const queue: ts.Node[] = [sourceFile]; let current: ts.Node; while (queue.length > 0) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion current = queue.shift()!; // find the child that contains 'position' for (const child of current.getChildren(sourceFile)) { @@ -26,5 +27,7 @@ export function getTokenAtPosition( } } } + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return current!; } diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index 5dcde889e8dd..191ed836a6a5 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -1,6 +1,5 @@ -/* eslint-disable @typescript-eslint/no-unnecessary-condition */ // There's lots of funny stuff due to the typing of ts.Node -/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-unnecessary-condition, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access */ import * as ts from 'typescript'; import { getDecorators, getModifiers } from './getModifiers'; diff --git a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts b/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts index 21178000ee5e..0277a2491d7f 100644 --- a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts +++ b/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts @@ -400,6 +400,7 @@ function maybeInvalidateProgram( * We need to make sure typescript knows this so it can update appropriately */ log('tsconfig has changed - triggering program update. %s', tsconfigPath); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion fileWatchCallbackTrackingMap .get(tsconfigPath)! .forEach(cb => cb(tsconfigPath, ts.FileWatcherEventKind.Changed)); @@ -431,6 +432,7 @@ function maybeInvalidateProgram( if (currentDir !== current) { cb(currentDir, ts.FileWatcherEventKind.Changed); } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion cb(current!, ts.FileWatcherEventKind.Changed); }); hasCallback = true; diff --git a/packages/typescript-estree/src/create-program/useProvidedPrograms.ts b/packages/typescript-estree/src/create-program/useProvidedPrograms.ts index 6c6e770bd20c..cae07bda5fa1 100644 --- a/packages/typescript-estree/src/create-program/useProvidedPrograms.ts +++ b/packages/typescript-estree/src/create-program/useProvidedPrograms.ts @@ -78,7 +78,9 @@ function createProgramFromConfigFile( useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames, }, ); - const result = parsed!; // parsed is not undefined, since we throw on failure. + // parsed is not undefined, since we throw on failure. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const result = parsed!; if (result.errors.length) { throw new Error(formatDiagnostics(result.errors)); } diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index aeef8d1e45ff..7d4da1ab84bb 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -243,7 +243,8 @@ function parseAndGenerateServices( options.filePath && parseAndGenerateServicesCalls[options.filePath] > 1 ? createIsolatedProgram(parseSettings) - : getProgramAndAST(parseSettings, hasFullTypeInformation)!; + : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + getProgramAndAST(parseSettings, hasFullTypeInformation)!; /** * Convert the TypeScript AST to an ESTree-compatible one, and optionally preserve diff --git a/packages/typescript-estree/src/useProgramFromProjectService.ts b/packages/typescript-estree/src/useProgramFromProjectService.ts index 59f6b0fe50ab..a5fa25b4b3bd 100644 --- a/packages/typescript-estree/src/useProgramFromProjectService.ts +++ b/packages/typescript-estree/src/useProgramFromProjectService.ts @@ -20,10 +20,12 @@ export function useProgramFromProjectService( } const scriptInfo = projectService.getScriptInfo(parseSettings.filePath); + /* eslint-disable @typescript-eslint/no-non-null-assertion */ const program = projectService .getDefaultProjectForFile(scriptInfo!.fileName, true)! .getLanguageService(/*ensureSynchronized*/ true) .getProgram(); + /* eslint-enable @typescript-eslint/no-non-null-assertion */ if (!program) { return undefined; diff --git a/packages/website/src/components/config/ConfigTypeScript.tsx b/packages/website/src/components/config/ConfigTypeScript.tsx index fb41fafc1976..a0aaa41ca3cf 100644 --- a/packages/website/src/components/config/ConfigTypeScript.tsx +++ b/packages/website/src/components/config/ConfigTypeScript.tsx @@ -34,6 +34,7 @@ function ConfigTypeScript(props: ConfigTypeScriptProps): React.JSX.Element { return Object.values( getTypescriptOptions().reduce>( (group, item) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const category = item.category!.message; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition group[category] ??= { @@ -44,12 +45,14 @@ function ConfigTypeScript(props: ConfigTypeScriptProps): React.JSX.Element { group[category].fields.push({ key: item.name, type: 'boolean', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion label: item.description!.message, }); } else if (item.type instanceof Map) { group[category].fields.push({ key: item.name, type: 'string', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion label: item.description!.message, enum: ['', ...Array.from(item.type.keys())], }); diff --git a/packages/website/src/components/editor/LoadedEditor.tsx b/packages/website/src/components/editor/LoadedEditor.tsx index f5bc9d244bf1..4d8ac07fd142 100644 --- a/packages/website/src/components/editor/LoadedEditor.tsx +++ b/packages/website/src/components/editor/LoadedEditor.tsx @@ -56,6 +56,7 @@ export const LoadedEditor: React.FC = ({ const codeActions = useRef(new Map()).current; const [tabs] = useState>(() => { const tabsDefault = { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion code: editor.getModel()!, tsconfig: monaco.editor.createModel( tsconfig, @@ -75,6 +76,7 @@ export const LoadedEditor: React.FC = ({ }); const updateMarkers = useCallback(() => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const model = editor.getModel()!; const markers = monaco.editor.getModelMarkers({ resource: model.uri, @@ -127,6 +129,7 @@ export const LoadedEditor: React.FC = ({ monaco.Uri.parse(webLinter.rules.get(ruleId)?.url ?? ''), ); monaco.editor.setModelMarkers( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion monaco.editor.getModel(monaco.Uri.file(uri))!, 'eslint', diagnostics, diff --git a/packages/website/src/components/editor/useSandboxServices.ts b/packages/website/src/components/editor/useSandboxServices.ts index 997cc1cc6058..b167a71ab469 100644 --- a/packages/website/src/components/editor/useSandboxServices.ts +++ b/packages/website/src/components/editor/useSandboxServices.ts @@ -114,6 +114,7 @@ export const useSandboxServices = ( return; } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const editorModel = sandboxInstance.editor.getModel()!; sandboxInstance.monaco.editor.setModelMarkers( editorModel, diff --git a/packages/website/src/components/hooks/useHashState.ts b/packages/website/src/components/hooks/useHashState.ts index 95573ba375b4..0762bb82051e 100644 --- a/packages/website/src/components/hooks/useHashState.ts +++ b/packages/website/src/components/hooks/useHashState.ts @@ -81,6 +81,7 @@ const parseStateFromUrl = (hash: string): Partial | undefined => { : ''; return { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ts: searchParams.get('ts') ?? process.env.TS_VERSION!, showAST: readShowAST(searchParams.get('showAST')), sourceType: diff --git a/packages/website/src/components/lib/jsonSchema.ts b/packages/website/src/components/lib/jsonSchema.ts index e5c5801583dd..4eb8009f9f34 100644 --- a/packages/website/src/components/lib/jsonSchema.ts +++ b/packages/website/src/components/lib/jsonSchema.ts @@ -175,6 +175,7 @@ export function getTypescriptJsonSchema(): JSONSchema4 { if (item.type === 'boolean') { options[item.name] = { type: 'boolean', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion description: item.description!.message, }; } else if (item.type === 'list' && item.element?.type instanceof Map) { @@ -184,11 +185,13 @@ export function getTypescriptJsonSchema(): JSONSchema4 { type: 'string', enum: Array.from(item.element.type.keys()), }, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion description: item.description!.message, }; } else if (item.type instanceof Map) { options[item.name] = { type: 'string', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion description: item.description!.message, enum: Array.from(item.type.keys()), }; diff --git a/packages/website/src/components/lib/shallowEqual.ts b/packages/website/src/components/lib/shallowEqual.ts index fc6909430cf8..8d18403fe72b 100644 --- a/packages/website/src/components/lib/shallowEqual.ts +++ b/packages/website/src/components/lib/shallowEqual.ts @@ -14,6 +14,7 @@ export function shallowEqual( return false; } for (const key of keys1) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (object1![key] !== object2![key]) { return false; } diff --git a/packages/website/src/components/linter/createParser.ts b/packages/website/src/components/linter/createParser.ts index ee509fed0acf..71768bf61414 100644 --- a/packages/website/src/components/linter/createParser.ts +++ b/packages/website/src/components/linter/createParser.ts @@ -67,6 +67,7 @@ export function createParser( throw new Error('Failed to get program'); } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const tsAst = program.getSourceFile(filePath)!; const converted = utils.astConverter(tsAst, parseSettings, true); diff --git a/packages/website/src/components/linter/utils.ts b/packages/website/src/components/linter/utils.ts index 4d01c8708dd5..aeb68da0181a 100644 --- a/packages/website/src/components/linter/utils.ts +++ b/packages/website/src/components/linter/utils.ts @@ -80,6 +80,7 @@ export function parseMarkers( isPreferred: item.isPreferred, fix(): void { editor.executeEdits('eslint', [ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion createEditOperation(editor.getModel()!, item), ]); }, diff --git a/packages/website/src/components/options.ts b/packages/website/src/components/options.ts index f52e7784bc37..851fae14cf08 100644 --- a/packages/website/src/components/options.ts +++ b/packages/website/src/components/options.ts @@ -33,6 +33,7 @@ export const defaultConfig: ConfigModel = { showAST: false, sourceType: 'module', code: '', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ts: process.env.TS_VERSION!, tsconfig: toJson({ compilerOptions: { diff --git a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx index 365dd15b1e8d..ab8db8723b14 100644 --- a/packages/website/src/theme/MDXComponents/RuleAttributes.tsx +++ b/packages/website/src/theme/MDXComponents/RuleAttributes.tsx @@ -21,6 +21,7 @@ const recommendations = { }; const getRecommendation = (docs: RuleMetaDataDocs): string[] => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const recommendation = recommendations[docs.recommended!]; return docs.requiresTypeChecking From 63cac6bebfa02bfb08a477410a992ac564c701e1 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 3 Feb 2024 10:57:42 -0500 Subject: [PATCH 2/5] Touched upmost website and tools --- .../tools/generate-breaking-changes.mts | 15 +++++++++---- packages/repo-tools/src/generate-lib.ts | 10 +++++---- packages/type-utils/src/getTokenAtPosition.ts | 4 ++-- .../getWatchProgramsForProjects.ts | 7 +++--- packages/typescript-estree/src/parser.ts | 3 +-- .../components/config/ConfigTypeScript.tsx | 9 +++----- .../src/components/editor/LoadedEditor.tsx | 11 +++++----- .../components/editor/useSandboxServices.ts | 7 ++++-- .../src/components/hooks/useHashState.ts | 3 +-- .../website/src/components/lib/jsonSchema.ts | 22 ++++++++++--------- .../src/components/lib/shallowEqual.ts | 2 ++ .../website/src/components/linter/utils.ts | 20 ++++++++--------- packages/website/src/components/options.ts | 3 +-- .../theme/MDXComponents/RuleAttributes.tsx | 13 +++++++---- packages/website/src/types.d.ts | 14 +++++++----- 15 files changed, 78 insertions(+), 65 deletions(-) diff --git a/packages/eslint-plugin/tools/generate-breaking-changes.mts b/packages/eslint-plugin/tools/generate-breaking-changes.mts index c983351be553..dd57b2042bc5 100644 --- a/packages/eslint-plugin/tools/generate-breaking-changes.mts +++ b/packages/eslint-plugin/tools/generate-breaking-changes.mts @@ -1,8 +1,13 @@ import type { TypeScriptESLintRules } from '@typescript-eslint/eslint-plugin/use-at-your-own-risk/rules'; +import type { RuleModule } from '@typescript-eslint/utils/ts-eslint'; import { fetch } from 'cross-fetch'; // markdown-table is ESM, hence this file needs to be `.mts` import { markdownTable } from 'markdown-table'; +type RuleModuleWithDocs = RuleModule & { + meta: { docs: object }; +}; + async function main(): Promise { const rulesImport = await import('../src/rules/index.js'); /* @@ -10,8 +15,11 @@ async function main(): Promise { { default: { default: Rules }} instead of just { default: Rules } - @ts-expect-error */ - const rules = rulesImport.default as TypeScriptESLintRules; + */ + const rules = rulesImport.default as unknown as Record< + string, + RuleModuleWithDocs + >; // Annotate which rules are new since the last version async function getNewRulesAsOfMajorVersion( @@ -131,8 +139,7 @@ async function main(): Promise { ...Object.entries(rules).map(([ruleName, { meta }]) => { const { deprecated } = meta; const { extendsBaseRule, recommended, requiresTypeChecking } = - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - meta.docs!; + meta.docs; return [ `[\`${ruleName}\`](https://typescript-eslint.io/rules/${ruleName})`, diff --git a/packages/repo-tools/src/generate-lib.ts b/packages/repo-tools/src/generate-lib.ts index 6fae4166ce65..c73a240f8510 100644 --- a/packages/repo-tools/src/generate-lib.ts +++ b/packages/repo-tools/src/generate-lib.ts @@ -119,10 +119,9 @@ function getVariablesFromScope(scopeManager: ScopeManager): Variable[] { const REFERENCE_REGEX = /\/ /; function getReferences( - ast: TSESTree.Program & { comments?: TSESTree.Comment[] }, + ast: TSESTree.Program & { comments: TSESTree.Comment[] }, ): Set { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const comments = ast.comments!.filter( + const comments = ast.comments.filter( c => c.type === AST_TOKEN_TYPES.Line && c.value.startsWith('/