From 41d8b51af5ffd29884ea49411af85d9fa1881bf3 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Mon, 18 Sep 2023 18:33:32 +0800 Subject: [PATCH 1/5] refactor: use named export for `util` --- .../src/rules/adjacent-overload-signatures.ts | 16 +-- .../eslint-plugin/src/rules/array-type.ts | 6 +- .../eslint-plugin/src/rules/await-thenable.ts | 25 ++-- .../eslint-plugin/src/rules/ban-ts-comment.ts | 7 +- .../src/rules/ban-tslint-comment.ts | 4 +- packages/eslint-plugin/src/rules/ban-types.ts | 6 +- .../eslint-plugin/src/rules/block-spacing.ts | 14 ++- .../src/rules/class-literal-property-style.ts | 4 +- .../src/rules/class-methods-use-this.ts | 15 ++- .../eslint-plugin/src/rules/comma-dangle.ts | 16 ++- .../src/rules/consistent-type-assertions.ts | 25 ++-- .../src/rules/consistent-type-definitions.ts | 4 +- .../src/rules/consistent-type-exports.ts | 42 ++++--- .../src/rules/consistent-type-imports.ts | 114 ++++++++++-------- .../src/rules/enum-utils/shared.ts | 4 +- .../rules/explicit-function-return-type.ts | 4 +- .../rules/explicit-member-accessibility.ts | 8 +- .../rules/explicit-module-boundary-types.ts | 6 +- .../src/rules/func-call-spacing.ts | 18 ++- packages/eslint-plugin/src/rules/indent.ts | 12 +- .../eslint-plugin/src/rules/key-spacing.ts | 23 ++-- .../src/rules/keyword-spacing.ts | 18 +-- .../src/rules/lines-around-comment.ts | 28 +++-- .../src/rules/lines-between-class-members.ts | 14 ++- .../src/rules/member-delimiter-style.ts | 8 +- .../src/rules/member-ordering.ts | 17 ++- .../src/rules/method-signature-style.ts | 21 ++-- .../naming-convention-utils/parse-options.ts | 4 +- .../rules/naming-convention-utils/schema.ts | 17 ++- .../naming-convention-utils/validator.ts | 4 +- .../src/rules/naming-convention.ts | 15 ++- .../src/rules/no-array-constructor.ts | 6 +- .../src/rules/no-base-to-string.ts | 12 +- .../rules/no-confusing-non-null-assertion.ts | 4 +- .../src/rules/no-confusing-void-expression.ts | 41 ++++--- .../src/rules/no-dupe-class-members.ts | 12 +- .../src/rules/no-duplicate-enum-values.ts | 4 +- .../rules/no-duplicate-type-constituents.ts | 6 +- .../src/rules/no-dynamic-delete.ts | 4 +- .../src/rules/no-empty-function.ts | 14 ++- .../src/rules/no-empty-interface.ts | 6 +- .../src/rules/no-explicit-any.ts | 4 +- .../src/rules/no-extra-non-null-assertion.ts | 4 +- .../src/rules/no-extra-parens.ts | 58 ++++----- .../eslint-plugin/src/rules/no-extra-semi.ts | 12 +- .../src/rules/no-extraneous-class.ts | 4 +- .../src/rules/no-floating-promises.ts | 14 ++- .../src/rules/no-for-in-array.ts | 15 ++- .../src/rules/no-implied-eval.ts | 6 +- .../src/rules/no-import-type-side-effects.ts | 22 ++-- .../src/rules/no-inferrable-types.ts | 4 +- .../src/rules/no-invalid-void-type.ts | 4 +- .../eslint-plugin/src/rules/no-loop-func.ts | 12 +- .../src/rules/no-loss-of-precision.ts | 14 ++- .../src/rules/no-magic-numbers.ts | 15 ++- .../src/rules/no-meaningless-void-operator.ts | 7 +- .../eslint-plugin/src/rules/no-misused-new.ts | 4 +- .../src/rules/no-misused-promises.ts | 10 +- .../eslint-plugin/src/rules/no-mixed-enums.ts | 6 +- .../eslint-plugin/src/rules/no-namespace.ts | 6 +- ...no-non-null-asserted-nullish-coalescing.ts | 11 +- .../no-non-null-asserted-optional-chain.ts | 4 +- .../src/rules/no-non-null-assertion.ts | 8 +- .../eslint-plugin/src/rules/no-redeclare.ts | 6 +- .../rules/no-redundant-type-constituents.ts | 34 ++++-- .../src/rules/no-require-imports.ts | 4 +- packages/eslint-plugin/src/rules/no-shadow.ts | 4 +- .../eslint-plugin/src/rules/no-this-alias.ts | 4 +- .../src/rules/no-throw-literal.ts | 15 ++- .../eslint-plugin/src/rules/no-type-alias.ts | 4 +- .../no-unnecessary-boolean-literal-compare.ts | 8 +- .../src/rules/no-unnecessary-qualifier.ts | 6 +- .../rules/no-unnecessary-type-arguments.ts | 17 ++- .../rules/no-unnecessary-type-assertion.ts | 34 +++--- .../rules/no-unnecessary-type-constraint.ts | 4 +- .../src/rules/no-unsafe-argument.ts | 29 +++-- .../src/rules/no-unsafe-assignment.ts | 53 ++++---- .../eslint-plugin/src/rules/no-unsafe-call.ts | 21 ++-- .../rules/no-unsafe-declaration-merging.ts | 4 +- .../src/rules/no-unsafe-enum-comparison.ts | 10 +- .../src/rules/no-unsafe-member-access.ts | 21 ++-- .../src/rules/no-unsafe-return.ts | 48 +++++--- .../src/rules/no-unused-expressions.ts | 12 +- .../eslint-plugin/src/rules/no-unused-vars.ts | 24 ++-- .../src/rules/no-use-before-define.ts | 4 +- .../src/rules/no-useless-constructor.ts | 12 +- .../src/rules/no-useless-empty-export.ts | 4 +- .../src/rules/no-var-requires.ts | 4 +- .../non-nullable-type-assertion-style.ts | 17 ++- .../rules/padding-line-between-statements.ts | 28 +++-- .../src/rules/parameter-properties.ts | 4 +- .../src/rules/prefer-as-const.ts | 4 +- .../src/rules/prefer-enum-initializers.ts | 4 +- .../eslint-plugin/src/rules/prefer-for-of.ts | 4 +- .../src/rules/prefer-function-type.ts | 4 +- .../src/rules/prefer-namespace-keyword.ts | 4 +- .../src/rules/prefer-nullish-coalescing.ts | 37 ++++-- .../analyzeChain.ts | 42 +++---- .../gatherLogicalOperands.ts | 7 +- .../src/rules/prefer-optional-chain.ts | 15 ++- .../rules/prefer-readonly-parameter-types.ts | 25 ++-- .../src/rules/prefer-readonly.ts | 7 +- .../src/rules/prefer-reduce-type-parameter.ts | 18 +-- .../src/rules/prefer-ts-expect-error.ts | 4 +- .../src/rules/promise-function-async.ts | 22 ++-- packages/eslint-plugin/src/rules/quotes.ts | 12 +- .../src/rules/require-array-sort-compare.ts | 23 ++-- .../eslint-plugin/src/rules/require-await.ts | 36 +++--- .../src/rules/restrict-plus-operands.ts | 20 +-- .../rules/restrict-template-expressions.ts | 33 ++--- .../eslint-plugin/src/rules/return-await.ts | 21 ++-- packages/eslint-plugin/src/rules/semi.ts | 12 +- .../src/rules/sort-type-constituents.ts | 5 +- .../src/rules/space-before-blocks.ts | 14 ++- .../src/rules/space-before-function-paren.ts | 10 +- .../src/rules/space-infix-ops.ts | 14 ++- .../src/rules/strict-boolean-expressions.ts | 90 +++++++------- .../src/rules/triple-slash-reference.ts | 4 +- .../src/rules/type-annotation-spacing.ts | 4 +- packages/eslint-plugin/src/rules/typedef.ts | 4 +- .../eslint-plugin/src/rules/unbound-method.ts | 14 ++- .../src/rules/unified-signatures.ts | 11 +- .../tests/areOptionsValid.test.ts | 4 +- packages/eslint-plugin/tests/util.test.ts | 8 +- .../tests/util/getWrappedCode.test.ts | 14 ++- 125 files changed, 1077 insertions(+), 780 deletions(-) diff --git a/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts b/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts index 0534cc8ce0d1..8af3cee44af2 100644 --- a/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts +++ b/packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, getNameFromMember, MemberNameType } from '../util'; type RuleNode = | TSESTree.BlockStatement @@ -15,7 +15,7 @@ type Member = | TSESTree.ProgramStatement | TSESTree.TypeElement; -export default util.createRule({ +export default createRule({ name: 'adjacent-overload-signatures', meta: { type: 'suggestion', @@ -36,7 +36,7 @@ export default util.createRule({ name: string; static: boolean; callSignature: boolean; - type: util.MemberNameType; + type: MemberNameType; } /** @@ -72,12 +72,12 @@ export default util.createRule({ name, static: isStatic, callSignature: false, - type: util.MemberNameType.Normal, + type: MemberNameType.Normal, }; } case AST_NODE_TYPES.TSMethodSignature: return { - ...util.getNameFromMember(member, sourceCode), + ...getNameFromMember(member, sourceCode), static: isStatic, callSignature: false, }; @@ -86,18 +86,18 @@ export default util.createRule({ name: 'call', static: isStatic, callSignature: true, - type: util.MemberNameType.Normal, + type: MemberNameType.Normal, }; case AST_NODE_TYPES.TSConstructSignatureDeclaration: return { name: 'new', static: isStatic, callSignature: false, - type: util.MemberNameType.Normal, + type: MemberNameType.Normal, }; case AST_NODE_TYPES.MethodDefinition: return { - ...util.getNameFromMember(member, sourceCode), + ...getNameFromMember(member, sourceCode), static: isStatic, callSignature: false, }; diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts index cd4a1f89cb2f..bc45356ae4ab 100644 --- a/packages/eslint-plugin/src/rules/array-type.ts +++ b/packages/eslint-plugin/src/rules/array-type.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, isParenthesized } from '../util'; /** * Check whatever node can be considered as simple @@ -85,7 +85,7 @@ type MessageIds = | 'errorStringGeneric' | 'errorStringGenericSimple'; -export default util.createRule({ +export default createRule({ name: 'array-type', meta: { type: 'suggestion', @@ -254,7 +254,7 @@ export default util.createRule({ const parentParens = readonlyPrefix && node.parent?.type === AST_NODE_TYPES.TSArrayType && - !util.isParenthesized(node.parent.elementType, sourceCode); + !isParenthesized(node.parent.elementType, sourceCode); const start = `${parentParens ? '(' : ''}${readonlyPrefix}${ typeParens ? '(' : '' diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index f5932dd7f259..37b6ad1c6dd4 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,9 +1,17 @@ import type { TSESLint } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; -import * as util from '../util'; +import { + createRule, + getParserServices, + isAwaitKeyword, + isTypeAnyType, + isTypeUnknownType, + nullThrows, + NullThrowsReasons, +} from '../util'; -export default util.createRule({ +export default createRule({ name: 'await-thenable', meta: { docs: { @@ -22,13 +30,13 @@ export default util.createRule({ defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); return { AwaitExpression(node): void { const type = services.getTypeAtLocation(node.argument); - if (util.isTypeAnyType(type) || util.isTypeUnknownType(type)) { + if (isTypeAnyType(type) || isTypeUnknownType(type)) { return; } @@ -43,12 +51,9 @@ export default util.createRule({ messageId: 'removeAwait', fix(fixer): TSESLint.RuleFix { const sourceCode = context.getSourceCode(); - const awaitKeyword = util.nullThrows( - sourceCode.getFirstToken(node, util.isAwaitKeyword), - util.NullThrowsReasons.MissingToken( - 'await', - 'await expression', - ), + const awaitKeyword = nullThrows( + sourceCode.getFirstToken(node, isAwaitKeyword), + NullThrowsReasons.MissingToken('await', 'await expression'), ); return fixer.remove(awaitKeyword); diff --git a/packages/eslint-plugin/src/rules/ban-ts-comment.ts b/packages/eslint-plugin/src/rules/ban-ts-comment.ts index 7de0718bde6b..4f64e85f5b9c 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-comment.ts @@ -1,6 +1,6 @@ import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, getStringLength } from '../util'; type DirectiveConfig = | boolean @@ -22,7 +22,7 @@ type MessageIds = | 'tsDirectiveCommentDescriptionNotMatchPattern' | 'tsDirectiveCommentRequiresDescription'; -export default util.createRule<[Options], MessageIds>({ +export default createRule<[Options], MessageIds>({ name: 'ban-ts-comment', meta: { type: 'problem', @@ -146,8 +146,7 @@ export default util.createRule<[Options], MessageIds>({ } = options; const format = descriptionFormats.get(fullDirective); if ( - util.getStringLength(description.trim()) < - minimumDescriptionLength + getStringLength(description.trim()) < minimumDescriptionLength ) { context.report({ data: { directive, minimumDescriptionLength }, diff --git a/packages/eslint-plugin/src/rules/ban-tslint-comment.ts b/packages/eslint-plugin/src/rules/ban-tslint-comment.ts index 4453649b717e..4e3814245617 100644 --- a/packages/eslint-plugin/src/rules/ban-tslint-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-tslint-comment.ts @@ -1,6 +1,6 @@ import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; // tslint regex // https://github.com/palantir/tslint/blob/95d9d958833fd9dc0002d18cbe34db20d0fbf437/src/enableDisableRules.ts#L32 @@ -15,7 +15,7 @@ const toText = ( ? ['//', text.trim()].join(' ') : ['/*', text.trim(), '*/'].join(' '); -export default util.createRule({ +export default createRule({ name: 'ban-tslint-comment', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/ban-types.ts b/packages/eslint-plugin/src/rules/ban-types.ts index 8352eff2f2d6..7e81dd58cde9 100644 --- a/packages/eslint-plugin/src/rules/ban-types.ts +++ b/packages/eslint-plugin/src/rules/ban-types.ts @@ -1,7 +1,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, objectReduceKey } from '../util'; type Types = Record< string, @@ -124,7 +124,7 @@ export const TYPE_KEYWORDS = { void: AST_NODE_TYPES.TSVoidKeyword, }; -export default util.createRule({ +export default createRule({ name: 'ban-types', meta: { type: 'suggestion', @@ -256,7 +256,7 @@ export default util.createRule({ }); } - const keywordSelectors = util.objectReduceKey( + const keywordSelectors = objectReduceKey( TYPE_KEYWORDS, (acc: TSESLint.RuleListener, keyword) => { if (bannedTypes.has(keyword)) { diff --git a/packages/eslint-plugin/src/rules/block-spacing.ts b/packages/eslint-plugin/src/rules/block-spacing.ts index 8141a979cf04..f66179002db9 100644 --- a/packages/eslint-plugin/src/rules/block-spacing.ts +++ b/packages/eslint-plugin/src/rules/block-spacing.ts @@ -1,15 +1,19 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, isTokenOnSameLine } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('block-spacing'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'block-spacing', meta: { type: 'layout', @@ -58,7 +62,7 @@ export default util.createRule({ */ function isValid(left: TSESTree.Token, right: TSESTree.Token): boolean { return ( - !util.isTokenOnSameLine(left, right) || + !isTokenOnSameLine(left, right) || sourceCode.isSpaceBetween!(left, right) === always ); } diff --git a/packages/eslint-plugin/src/rules/class-literal-property-style.ts b/packages/eslint-plugin/src/rules/class-literal-property-style.ts index bd9e0895e719..d771d4bb273d 100644 --- a/packages/eslint-plugin/src/rules/class-literal-property-style.ts +++ b/packages/eslint-plugin/src/rules/class-literal-property-style.ts @@ -1,7 +1,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Options = ['fields' | 'getters']; type MessageIds = @@ -40,7 +40,7 @@ const isSupportedLiteral = ( return false; }; -export default util.createRule({ +export default createRule({ name: 'class-literal-property-style', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/class-methods-use-this.ts b/packages/eslint-plugin/src/rules/class-methods-use-this.ts index 948aa4def5ba..3ed2667fe5a5 100644 --- a/packages/eslint-plugin/src/rules/class-methods-use-this.ts +++ b/packages/eslint-plugin/src/rules/class-methods-use-this.ts @@ -1,7 +1,12 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + getFunctionHeadLoc, + getFunctionNameWithKind, + getStaticStringValue, +} from '../util'; type Options = [ { @@ -13,7 +18,7 @@ type Options = [ ]; type MessageIds = 'missingThis'; -export default util.createRule({ +export default createRule({ name: 'class-methods-use-this', meta: { type: 'suggestion', @@ -164,7 +169,7 @@ export default util.createRule({ node.key.type === AST_NODE_TYPES.PrivateIdentifier ? '#' : ''; const name = node.key.type === AST_NODE_TYPES.Literal - ? util.getStaticStringValue(node.key) + ? getStaticStringValue(node.key) : node.key.name || ''; return !exceptMethods.has(hashIfNeeded + (name ?? '')); @@ -193,10 +198,10 @@ export default util.createRule({ if (isIncludedInstanceMethod(stackContext.member)) { context.report({ node, - loc: util.getFunctionHeadLoc(node, sourceCode), + loc: getFunctionHeadLoc(node, sourceCode), messageId: 'missingThis', data: { - name: util.getFunctionNameWithKind(node), + name: getFunctionNameWithKind(node), }, }); } diff --git a/packages/eslint-plugin/src/rules/comma-dangle.ts b/packages/eslint-plugin/src/rules/comma-dangle.ts index 125cb47a325d..5edc00499041 100644 --- a/packages/eslint-plugin/src/rules/comma-dangle.ts +++ b/packages/eslint-plugin/src/rules/comma-dangle.ts @@ -1,13 +1,17 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, isCommaToken } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('comma-dangle'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; type Option = Options[0]; type NormalizedOptions = Required< @@ -38,7 +42,7 @@ function normalizeOptions(options: Option): NormalizedOptions { }; } -export default util.createRule({ +export default createRule({ name: 'comma-dangle', meta: { type: 'layout', @@ -135,7 +139,7 @@ export default util.createRule({ function forbidComma(node: TSESTree.Node): void { const last = getLastItem(node); const trailing = getTrailingToken(node); - if (last && trailing && util.isCommaToken(trailing)) { + if (last && trailing && isCommaToken(trailing)) { context.report({ node, messageId: 'unexpected', @@ -149,7 +153,7 @@ export default util.createRule({ function forceComma(node: TSESTree.Node): void { const last = getLastItem(node); const trailing = getTrailingToken(node); - if (last && trailing && !util.isCommaToken(trailing)) { + if (last && trailing && !isCommaToken(trailing)) { context.report({ node, messageId: 'missing', diff --git a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts index d2e610255f17..0c3883f81809 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-assertions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-assertions.ts @@ -2,7 +2,14 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getOperatorPrecedence, + getParserServices, + isClosingParenToken, + isOpeningParenToken, + isParenthesized, +} from '../util'; import { getWrappedCode } from '../util/getWrappedCode'; // intentionally mirroring the options @@ -23,7 +30,7 @@ type OptUnion = }; export type Options = readonly [OptUnion]; -export default util.createRule({ +export default createRule({ name: 'consistent-type-assertions', meta: { type: 'suggestion', @@ -84,7 +91,7 @@ export default util.createRule({ ], create(context, [options]) { const sourceCode = context.getSourceCode(); - const parserServices = util.getParserServices(context, true); + const parserServices = getParserServices(context, true); function isConst(node: TSESTree.TypeNode): boolean { if (node.type !== AST_NODE_TYPES.TSTypeReference) { @@ -102,14 +109,14 @@ export default util.createRule({ let beforeCount = 0; let afterCount = 0; - if (util.isParenthesized(node, sourceCode)) { + if (isParenthesized(node, sourceCode)) { const bodyOpeningParen = sourceCode.getTokenBefore( node, - util.isOpeningParenToken, + isOpeningParenToken, )!; const bodyClosingParen = sourceCode.getTokenAfter( node, - util.isClosingParenToken, + isClosingParenToken, )!; beforeCount = node.range[0] - bodyOpeningParen.range[0]; @@ -151,11 +158,11 @@ export default util.createRule({ node.typeAnnotation, ); - const asPrecedence = util.getOperatorPrecedence( + const asPrecedence = getOperatorPrecedence( ts.SyntaxKind.AsExpression, ts.SyntaxKind.Unknown, ); - const parentPrecedence = util.getOperatorPrecedence( + const parentPrecedence = getOperatorPrecedence( tsNode.parent.kind, ts.isBinaryExpression(tsNode.parent) ? tsNode.parent.operatorToken.kind @@ -169,7 +176,7 @@ export default util.createRule({ const text = `${expressionCode} as ${typeAnnotationCode}`; return fixer.replaceText( node, - util.isParenthesized(node, sourceCode) + isParenthesized(node, sourceCode) ? text : getWrappedCode(text, asPrecedence, parentPrecedence), ); diff --git a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts index b504081ee4a1..2a9acedd14a5 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts @@ -1,9 +1,9 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'consistent-type-definitions', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/consistent-type-exports.ts b/packages/eslint-plugin/src/rules/consistent-type-exports.ts index 3c496ee63d61..36e27f91d73a 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-exports.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-exports.ts @@ -2,7 +2,15 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { SymbolFlags } from 'typescript'; -import * as util from '../util'; +import { + createRule, + formatWordList, + getParserServices, + isClosingBraceToken, + isOpeningBraceToken, + nullThrows, + NullThrowsReasons, +} from '../util'; type Options = [ { @@ -29,7 +37,7 @@ type MessageIds = | 'singleExportIsType' | 'typeOverValue'; -export default util.createRule({ +export default createRule({ name: 'consistent-type-exports', meta: { type: 'suggestion', @@ -68,7 +76,7 @@ export default util.createRule({ create(context, [{ fixMixedExportsWithInlineTypeSpecifier }]) { const sourceCode = context.getSourceCode(); const sourceExportsMap: Record = {}; - const services = util.getParserServices(context); + const services = getParserServices(context); /** * Helper for identifying if an export specifier resolves to a @@ -194,7 +202,7 @@ export default util.createRule({ }, }); } else { - const exportNames = util.formatWordList(allExportNames); + const exportNames = formatWordList(allExportNames); context.report({ node: report.node, @@ -229,20 +237,20 @@ function* fixExportInsertType( sourceCode: Readonly, node: TSESTree.ExportNamedDeclaration, ): IterableIterator { - const exportToken = util.nullThrows( + const exportToken = nullThrows( sourceCode.getFirstToken(node), - util.NullThrowsReasons.MissingToken('export', node.type), + NullThrowsReasons.MissingToken('export', node.type), ); yield fixer.insertTextAfter(exportToken, ' type'); for (const specifier of node.specifiers) { if (specifier.exportKind === 'type') { - const kindToken = util.nullThrows( + const kindToken = nullThrows( sourceCode.getFirstToken(specifier), - util.NullThrowsReasons.MissingToken('export', specifier.type), + NullThrowsReasons.MissingToken('export', specifier.type), ); - const firstTokenAfter = util.nullThrows( + const firstTokenAfter = nullThrows( sourceCode.getTokenAfter(kindToken, { includeComments: true, }), @@ -270,22 +278,22 @@ function* fixSeparateNamedExports( const source = getSourceFromExport(node); const specifierNames = typeSpecifiers.map(getSpecifierText).join(', '); - const exportToken = util.nullThrows( + const exportToken = nullThrows( sourceCode.getFirstToken(node), - util.NullThrowsReasons.MissingToken('export', node.type), + NullThrowsReasons.MissingToken('export', node.type), ); // Filter the bad exports from the current line. const filteredSpecifierNames = valueSpecifiers .map(getSpecifierText) .join(', '); - const openToken = util.nullThrows( - sourceCode.getFirstToken(node, util.isOpeningBraceToken), - util.NullThrowsReasons.MissingToken('{', node.type), + const openToken = nullThrows( + sourceCode.getFirstToken(node, isOpeningBraceToken), + NullThrowsReasons.MissingToken('{', node.type), ); - const closeToken = util.nullThrows( - sourceCode.getLastToken(node, util.isClosingBraceToken), - util.NullThrowsReasons.MissingToken('}', node.type), + const closeToken = nullThrows( + sourceCode.getLastToken(node, isClosingBraceToken), + NullThrowsReasons.MissingToken('}', node.type), ); // Remove exports from the current line which we're going to re-insert. diff --git a/packages/eslint-plugin/src/rules/consistent-type-imports.ts b/packages/eslint-plugin/src/rules/consistent-type-imports.ts index 9aaa296a4b0c..a99a09e7bc1c 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-imports.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-imports.ts @@ -1,7 +1,17 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + formatWordList, + isClosingBraceToken, + isCommaToken, + isImportKeyword, + isOpeningBraceToken, + isTypeKeyword, + nullThrows, + NullThrowsReasons, +} from '../util'; type Prefer = 'no-type-imports' | 'type-imports'; type FixStyle = 'inline-type-imports' | 'separate-type-imports'; @@ -40,7 +50,7 @@ type MessageIds = | 'someImportsInDecoMeta' | 'typeOverValue' | 'valueOverType'; -export default util.createRule({ +export default createRule({ name: 'consistent-type-imports', meta: { type: 'suggestion', @@ -287,7 +297,7 @@ export default util.createRule({ messageId: MessageIds; data: Record; } => { - const typeImports = util.formatWordList(importNames); + const typeImports = formatWordList(importNames); if (importNames.length === 1) { if (isTypeImport) { @@ -428,24 +438,24 @@ export default util.createRule({ if (subsetNamedSpecifiers.length === allNamedSpecifiers.length) { // import Foo, {Type1, Type2} from 'foo' // import DefType, {Type1, Type2} from 'foo' - const openingBraceToken = util.nullThrows( + const openingBraceToken = nullThrows( sourceCode.getTokenBefore( subsetNamedSpecifiers[0], - util.isOpeningBraceToken, + isOpeningBraceToken, ), - util.NullThrowsReasons.MissingToken('{', node.type), + NullThrowsReasons.MissingToken('{', node.type), ); - const commaToken = util.nullThrows( - sourceCode.getTokenBefore(openingBraceToken, util.isCommaToken), - util.NullThrowsReasons.MissingToken(',', node.type), + const commaToken = nullThrows( + sourceCode.getTokenBefore(openingBraceToken, isCommaToken), + NullThrowsReasons.MissingToken(',', node.type), ); - const closingBraceToken = util.nullThrows( + const closingBraceToken = nullThrows( sourceCode.getFirstTokenBetween( openingBraceToken, node.source, - util.isClosingBraceToken, + isClosingBraceToken, ), - util.NullThrowsReasons.MissingToken('}', node.type), + NullThrowsReasons.MissingToken('}', node.type), ); // import DefType, {...} from 'foo' @@ -506,7 +516,7 @@ export default util.createRule({ const textRange: TSESTree.Range = [...removeRange]; const before = sourceCode.getTokenBefore(first)!; textRange[0] = before.range[1]; - if (util.isCommaToken(before)) { + if (isCommaToken(before)) { removeRange[0] = before.range[0]; } else { removeRange[0] = before.range[1]; @@ -517,7 +527,7 @@ export default util.createRule({ const after = sourceCode.getTokenAfter(last)!; textRange[1] = after.range[0]; if (isFirst || isLast) { - if (util.isCommaToken(after)) { + if (isCommaToken(after)) { removeRange[1] = after.range[1]; } } @@ -539,16 +549,16 @@ export default util.createRule({ target: TSESTree.ImportDeclaration, insertText: string, ): TSESLint.RuleFix { - const closingBraceToken = util.nullThrows( + const closingBraceToken = nullThrows( sourceCode.getFirstTokenBetween( sourceCode.getFirstToken(target)!, target.source, - util.isClosingBraceToken, + isClosingBraceToken, ), - util.NullThrowsReasons.MissingToken('}', target.type), + NullThrowsReasons.MissingToken('}', target.type), ); const before = sourceCode.getTokenBefore(closingBraceToken)!; - if (!util.isCommaToken(before) && !util.isOpeningBraceToken(before)) { + if (!isCommaToken(before) && !isOpeningBraceToken(before)) { insertText = `,${insertText}`; } return fixer.insertTextBefore(closingBraceToken, insertText); @@ -710,9 +720,9 @@ export default util.createRule({ // import Foo, * as Type from 'foo' // import DefType, * as Type from 'foo' // import DefType, * as Type from 'foo' - const commaToken = util.nullThrows( - sourceCode.getTokenBefore(namespaceSpecifier, util.isCommaToken), - util.NullThrowsReasons.MissingToken(',', node.type), + const commaToken = nullThrows( + sourceCode.getTokenBefore(namespaceSpecifier, isCommaToken), + NullThrowsReasons.MissingToken(',', node.type), ); // import Def, * as Ns from 'foo' @@ -735,17 +745,17 @@ export default util.createRule({ report.typeSpecifiers.includes(defaultSpecifier) ) { if (report.typeSpecifiers.length === node.specifiers.length) { - const importToken = util.nullThrows( - sourceCode.getFirstToken(node, util.isImportKeyword), - util.NullThrowsReasons.MissingToken('import', node.type), + const importToken = nullThrows( + sourceCode.getFirstToken(node, isImportKeyword), + NullThrowsReasons.MissingToken('import', node.type), ); // import type Type from 'foo' // ^^^^ insert yield fixer.insertTextAfter(importToken, ' type'); } else { - const commaToken = util.nullThrows( - sourceCode.getTokenAfter(defaultSpecifier, util.isCommaToken), - util.NullThrowsReasons.MissingToken(',', defaultSpecifier.type), + const commaToken = nullThrows( + sourceCode.getTokenAfter(defaultSpecifier, isCommaToken), + NullThrowsReasons.MissingToken(',', defaultSpecifier.type), ); // import Type , {...} from 'foo' // ^^^^^ pick @@ -758,9 +768,9 @@ export default util.createRule({ node.source, )};\n`, ); - const afterToken = util.nullThrows( + const afterToken = nullThrows( sourceCode.getTokenAfter(commaToken, { includeComments: true }), - util.NullThrowsReasons.MissingToken('any token', node.type), + NullThrowsReasons.MissingToken('any token', node.type), ); // import Type , {...} from 'foo' // ^^^^^^^ remove @@ -784,9 +794,9 @@ export default util.createRule({ ): IterableIterator { // import type Foo from 'foo' // ^^^^^ insert - const importToken = util.nullThrows( - sourceCode.getFirstToken(node, util.isImportKeyword), - util.NullThrowsReasons.MissingToken('import', node.type), + const importToken = nullThrows( + sourceCode.getFirstToken(node, isImportKeyword), + NullThrowsReasons.MissingToken('import', node.type), ); yield fixer.insertTextAfter(importToken, ' type'); @@ -795,21 +805,21 @@ export default util.createRule({ const openingBraceToken = sourceCode.getFirstTokenBetween( importToken, node.source, - util.isOpeningBraceToken, + isOpeningBraceToken, ); if (openingBraceToken) { // Only braces. e.g. import Foo, {} from 'foo' - const commaToken = util.nullThrows( - sourceCode.getTokenBefore(openingBraceToken, util.isCommaToken), - util.NullThrowsReasons.MissingToken(',', node.type), + const commaToken = nullThrows( + sourceCode.getTokenBefore(openingBraceToken, isCommaToken), + NullThrowsReasons.MissingToken(',', node.type), ); - const closingBraceToken = util.nullThrows( + const closingBraceToken = nullThrows( sourceCode.getFirstTokenBetween( openingBraceToken, node.source, - util.isClosingBraceToken, + isClosingBraceToken, ), - util.NullThrowsReasons.MissingToken('}', node.type), + NullThrowsReasons.MissingToken('}', node.type), ); // import type Foo, {} from 'foo' @@ -929,21 +939,21 @@ export default util.createRule({ ): IterableIterator { // import type Foo from 'foo' // ^^^^ remove - const importToken = util.nullThrows( - sourceCode.getFirstToken(node, util.isImportKeyword), - util.NullThrowsReasons.MissingToken('import', node.type), + const importToken = nullThrows( + sourceCode.getFirstToken(node, isImportKeyword), + NullThrowsReasons.MissingToken('import', node.type), ); - const typeToken = util.nullThrows( + const typeToken = nullThrows( sourceCode.getFirstTokenBetween( importToken, node.specifiers[0]?.local ?? node.source, - util.isTypeKeyword, + isTypeKeyword, ), - util.NullThrowsReasons.MissingToken('type', node.type), + NullThrowsReasons.MissingToken('type', node.type), ); - const afterToken = util.nullThrows( + const afterToken = nullThrows( sourceCode.getTokenAfter(typeToken, { includeComments: true }), - util.NullThrowsReasons.MissingToken('any token', node.type), + NullThrowsReasons.MissingToken('any token', node.type), ); yield fixer.removeRange([typeToken.range[0], afterToken.range[0]]); } @@ -954,13 +964,13 @@ export default util.createRule({ ): IterableIterator { // import { type Foo } from 'foo' // ^^^^ remove - const typeToken = util.nullThrows( - sourceCode.getFirstToken(node, util.isTypeKeyword), - util.NullThrowsReasons.MissingToken('type', node.type), + const typeToken = nullThrows( + sourceCode.getFirstToken(node, isTypeKeyword), + NullThrowsReasons.MissingToken('type', node.type), ); - const afterToken = util.nullThrows( + const afterToken = nullThrows( sourceCode.getTokenAfter(typeToken, { includeComments: true }), - util.NullThrowsReasons.MissingToken('any token', node.type), + NullThrowsReasons.MissingToken('any token', node.type), ); yield fixer.removeRange([typeToken.range[0], afterToken.range[0]]); } diff --git a/packages/eslint-plugin/src/rules/enum-utils/shared.ts b/packages/eslint-plugin/src/rules/enum-utils/shared.ts index e629d00e7be7..39fca8af9113 100644 --- a/packages/eslint-plugin/src/rules/enum-utils/shared.ts +++ b/packages/eslint-plugin/src/rules/enum-utils/shared.ts @@ -1,7 +1,7 @@ import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../../util'; +import { isTypeFlagSet } from '../../util'; /* * If passed an enum member, returns the type of the parent. Otherwise, @@ -35,6 +35,6 @@ export function getEnumTypes( ): ts.Type[] { return tsutils .unionTypeParts(type) - .filter(subType => util.isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral)) + .filter(subType => isTypeFlagSet(subType, ts.TypeFlags.EnumLiteral)) .map(type => getBaseEnumType(typeChecker, type)); } 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 e57465be8365..59b223912c3b 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; import { ancestorHasReturnType, checkFunctionReturnType, @@ -22,7 +22,7 @@ type Options = [ ]; type MessageIds = 'missingReturnType'; -export default util.createRule({ +export default createRule({ name: 'explicit-function-return-type', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index d95a58dc281e..ff99eb77b4a8 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -1,7 +1,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, getNameFromMember } from '../util'; type AccessibilityLevel = | 'explicit' // require an accessor (including public) @@ -27,7 +27,7 @@ type MessageIds = | 'missingAccessibility' | 'unwantedPublicAccessibility'; -export default util.createRule({ +export default createRule({ name: 'explicit-member-accessibility', meta: { hasSuggestions: true, @@ -135,7 +135,7 @@ export default util.createRule({ break; } - const { name: methodName } = util.getNameFromMember( + const { name: methodName } = getNameFromMember( methodDefinition, sourceCode, ); @@ -269,7 +269,7 @@ export default util.createRule({ const nodeType = 'class property'; - const { name: propertyName } = util.getNameFromMember( + const { name: propertyName } = getNameFromMember( propertyDefinition, sourceCode, ); 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 1ac7e70bb9f8..d2cb5f5306f8 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -2,7 +2,7 @@ import { DefinitionType } from '@typescript-eslint/scope-manager'; import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, isFunction } from '../util'; import type { FunctionExpression, FunctionNode, @@ -31,7 +31,7 @@ type MessageIds = | 'missingArgTypeUnnamed' | 'missingReturnType'; -export default util.createRule({ +export default createRule({ name: 'explicit-module-boundary-types', meta: { type: 'problem', @@ -277,7 +277,7 @@ export default util.createRule({ } if ( - !util.isFunction(current) || + !isFunction(current) || !doesImmediatelyReturnFunctionExpression(current) ) { return false; diff --git a/packages/eslint-plugin/src/rules/func-call-spacing.ts b/packages/eslint-plugin/src/rules/func-call-spacing.ts index b72c54951f92..95007fdcd3df 100644 --- a/packages/eslint-plugin/src/rules/func-call-spacing.ts +++ b/packages/eslint-plugin/src/rules/func-call-spacing.ts @@ -1,6 +1,12 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + isNotOptionalChainPunctuator, + isOpeningParenToken, + isOptionalCallExpression, + LINEBREAK_MATCHER, +} from '../util'; export type Options = [ 'always' | 'never', @@ -13,7 +19,7 @@ export type MessageIds = | 'unexpectedNewline' | 'unexpectedWhitespace'; -export default util.createRule({ +export default createRule({ name: 'func-call-spacing', meta: { type: 'layout', @@ -80,7 +86,7 @@ export default util.createRule({ function checkSpacing( node: TSESTree.CallExpression | TSESTree.NewExpression, ): void { - const isOptionalCall = util.isOptionalCallExpression(node); + const isOptionalCall = isOptionalCallExpression(node); const closingParenToken = sourceCode.getLastToken(node)!; const lastCalleeTokenWithoutPossibleParens = sourceCode.getLastToken( @@ -89,7 +95,7 @@ export default util.createRule({ const openingParenToken = sourceCode.getFirstTokenBetween( lastCalleeTokenWithoutPossibleParens, closingParenToken, - util.isOpeningParenToken, + isOpeningParenToken, ); if (!openingParenToken || openingParenToken.range[1] >= node.range[1]) { // new expression with no parens... @@ -97,7 +103,7 @@ export default util.createRule({ } const lastCalleeToken = sourceCode.getTokenBefore( openingParenToken, - util.isNotOptionalChainPunctuator, + isNotOptionalChainPunctuator, )!; const textBetweenTokens = text @@ -105,7 +111,7 @@ export default util.createRule({ .replace(/\/\*.*?\*\//gu, ''); const hasWhitespace = /\s/u.test(textBetweenTokens); const hasNewline = - hasWhitespace && util.LINEBREAK_MATCHER.test(textBetweenTokens); + hasWhitespace && LINEBREAK_MATCHER.test(textBetweenTokens); if (option === 'never') { if (hasWhitespace) { diff --git a/packages/eslint-plugin/src/rules/indent.ts b/packages/eslint-plugin/src/rules/indent.ts index adcf4152d3bc..ae8f6f60415d 100644 --- a/packages/eslint-plugin/src/rules/indent.ts +++ b/packages/eslint-plugin/src/rules/indent.ts @@ -8,13 +8,17 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('indent'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; const KNOWN_NODES = new Set([ // Class properties aren't yet supported by eslint... @@ -84,7 +88,7 @@ const KNOWN_NODES = new Set([ AST_NODE_TYPES.Decorator, ]); -export default util.createRule({ +export default createRule({ name: 'indent', meta: { type: 'layout', diff --git a/packages/eslint-plugin/src/rules/key-spacing.ts b/packages/eslint-plugin/src/rules/key-spacing.ts index 20d7f577ecfb..707c9dc4431b 100644 --- a/packages/eslint-plugin/src/rules/key-spacing.ts +++ b/packages/eslint-plugin/src/rules/key-spacing.ts @@ -1,13 +1,22 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { + createRule, + getStringLength, + isClosingBracketToken, + isColonToken, +} from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('key-spacing'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const baseSchema = Array.isArray(baseRule.meta.schema) @@ -24,7 +33,7 @@ function at(arr: T[], position: number): T | undefined { return arr[position]; } -export default util.createRule({ +export default createRule({ name: 'key-spacing', meta: { type: 'layout', @@ -49,7 +58,7 @@ export default util.createRule({ */ function adjustedColumn(position: TSESTree.Position): number { const line = position.line - 1; // position.line is 1-indexed - return util.getStringLength( + return getStringLength( at(sourceCode.lines, line)!.slice(0, position.column), ); } @@ -59,7 +68,7 @@ export default util.createRule({ * until it finds the last token before a colon punctuator and returns it. */ function getLastTokenBeforeColon(node: TSESTree.Node): TSESTree.Token { - const colonToken = sourceCode.getTokenAfter(node, util.isColonToken)!; + const colonToken = sourceCode.getTokenAfter(node, isColonToken)!; return sourceCode.getTokenBefore(colonToken)!; } @@ -106,7 +115,7 @@ export default util.createRule({ 0, sourceCode.getTokenAfter( at(node.parameters, -1)!, - util.isClosingBracketToken, + isClosingBracketToken, )!.range[1] - node.range[0], ); } diff --git a/packages/eslint-plugin/src/rules/keyword-spacing.ts b/packages/eslint-plugin/src/rules/keyword-spacing.ts index 893c70db7674..50fbdc18d22b 100644 --- a/packages/eslint-plugin/src/rules/keyword-spacing.ts +++ b/packages/eslint-plugin/src/rules/keyword-spacing.ts @@ -2,19 +2,23 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, deepMerge, nullThrows, NullThrowsReasons } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('keyword-spacing'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const baseSchema = Array.isArray(baseRule.meta.schema) ? baseRule.meta.schema[0] : baseRule.meta.schema; -const schema = util.deepMerge( +const schema = deepMerge( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- https://github.com/microsoft/TypeScript/issues/17002 baseSchema, { @@ -29,7 +33,7 @@ const schema = util.deepMerge( }, ) as unknown as JSONSchema4; -export default util.createRule({ +export default createRule({ name: 'keyword-spacing', meta: { type: 'layout', @@ -50,12 +54,12 @@ export default util.createRule({ return { ...baseRules, TSAsExpression(node): void { - const asToken = util.nullThrows( + const asToken = nullThrows( sourceCode.getTokenAfter( node.expression, token => token.value === 'as', ), - util.NullThrowsReasons.MissingToken('as', node.type), + NullThrowsReasons.MissingToken('as', node.type), ); const oldTokenType = asToken.type; // as is a contextual keyword, so it's always reported as an Identifier diff --git a/packages/eslint-plugin/src/rules/lines-around-comment.ts b/packages/eslint-plugin/src/rules/lines-around-comment.ts index f7cdef33b2e4..1855c8ae5b8c 100644 --- a/packages/eslint-plugin/src/rules/lines-around-comment.ts +++ b/packages/eslint-plugin/src/rules/lines-around-comment.ts @@ -1,13 +1,17 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, isCommentToken, isTokenOnSameLine } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('lines-around-comment'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; const COMMENTS_IGNORE_PATTERN = /^\s*(?:eslint|jshint\s+|jslint\s+|istanbul\s+|globals?\s+|exported\s+|jscs)/u; @@ -42,7 +46,7 @@ function getCommentLineNums(comments: TSESTree.Comment[]): number[] { return lines; } -export default util.createRule({ +export default createRule({ name: 'lines-around-comment', meta: { type: 'layout', @@ -162,9 +166,9 @@ export default util.createRule({ currentToken = sourceCode.getTokenBefore(currentToken, { includeComments: true, }); - } while (currentToken && util.isCommentToken(currentToken)); + } while (currentToken && isCommentToken(currentToken)); - if (currentToken && util.isTokenOnSameLine(currentToken, token)) { + if (currentToken && isTokenOnSameLine(currentToken, token)) { return true; } @@ -173,9 +177,9 @@ export default util.createRule({ currentToken = sourceCode.getTokenAfter(currentToken, { includeComments: true, }); - } while (currentToken && util.isCommentToken(currentToken)); + } while (currentToken && isCommentToken(currentToken)); - if (currentToken && util.isTokenOnSameLine(token, currentToken)) { + if (currentToken && isTokenOnSameLine(token, currentToken)) { return true; } @@ -352,8 +356,8 @@ export default util.createRule({ before && !commentAndEmptyLines.has(prevLineNum) && !( - util.isCommentToken(previousTokenOrComment!) && - util.isTokenOnSameLine(previousTokenOrComment, token) + isCommentToken(previousTokenOrComment!) && + isTokenOnSameLine(previousTokenOrComment, token) ) ) { const lineStart = token.range[0] - token.loc.start.column; @@ -374,8 +378,8 @@ export default util.createRule({ after && !commentAndEmptyLines.has(nextLineNum) && !( - util.isCommentToken(nextTokenOrComment!) && - util.isTokenOnSameLine(token, nextTokenOrComment) + isCommentToken(nextTokenOrComment!) && + isTokenOnSameLine(token, nextTokenOrComment) ) ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/lines-between-class-members.ts b/packages/eslint-plugin/src/rules/lines-between-class-members.ts index e88e42d477af..2383142387a7 100644 --- a/packages/eslint-plugin/src/rules/lines-between-class-members.ts +++ b/packages/eslint-plugin/src/rules/lines-between-class-members.ts @@ -2,16 +2,20 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, deepMerge } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('lines-between-class-members'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; const schema = Object.values( - util.deepMerge( + deepMerge( { ...baseRule.meta.schema }, { 1: { @@ -26,7 +30,7 @@ const schema = Object.values( ), ) as JSONSchema4[]; -export default util.createRule({ +export default createRule({ name: 'lines-between-class-members', meta: { type: 'layout', diff --git a/packages/eslint-plugin/src/rules/member-delimiter-style.ts b/packages/eslint-plugin/src/rules/member-delimiter-style.ts index e0055a385e17..2a0880cd21fb 100644 --- a/packages/eslint-plugin/src/rules/member-delimiter-style.ts +++ b/packages/eslint-plugin/src/rules/member-delimiter-style.ts @@ -2,7 +2,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; -import * as util from '../util'; +import { createRule, deepMerge } from '../util'; type Delimiter = 'comma' | 'none' | 'semi'; // need type's implicit index sig for deepMerge @@ -132,7 +132,7 @@ const BASE_SCHEMA: JSONSchema4 = { additionalProperties: false, }; -export default util.createRule({ +export default createRule({ name: 'member-delimiter-style', meta: { type: 'layout', @@ -205,11 +205,11 @@ export default util.createRule({ // use the base options as the defaults for the cases const baseOptions = options; const overrides = baseOptions.overrides ?? {}; - const interfaceOptions: BaseOptions = util.deepMerge( + const interfaceOptions: BaseOptions = deepMerge( baseOptions, overrides.interface, ); - const typeLiteralOptions: BaseOptions = util.deepMerge( + const typeLiteralOptions: BaseOptions = deepMerge( baseOptions, overrides.typeLiteral, ); diff --git a/packages/eslint-plugin/src/rules/member-ordering.ts b/packages/eslint-plugin/src/rules/member-ordering.ts index f7ad60c58feb..84d34d4c596c 100644 --- a/packages/eslint-plugin/src/rules/member-ordering.ts +++ b/packages/eslint-plugin/src/rules/member-ordering.ts @@ -2,7 +2,12 @@ import type { JSONSchema, TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import naturalCompare from 'natural-compare'; -import * as util from '../util'; +import { + createRule, + getNameFromIndexSignature, + getNameFromMember, + MemberNameType, +} from '../util'; export type MessageIds = | 'incorrectGroupOrder' @@ -380,12 +385,12 @@ function getMemberRawName( | TSESTree.TSPropertySignature, sourceCode: TSESLint.SourceCode, ): string { - const { name, type } = util.getNameFromMember(member, sourceCode); + const { name, type } = getNameFromMember(member, sourceCode); - if (type === util.MemberNameType.Quoted) { + if (type === MemberNameType.Quoted) { return name.slice(1, -1); } - if (type === util.MemberNameType.Private) { + if (type === MemberNameType.Private) { return name.slice(1); } return name; @@ -417,7 +422,7 @@ function getMemberName( case AST_NODE_TYPES.TSCallSignatureDeclaration: return 'call'; case AST_NODE_TYPES.TSIndexSignature: - return util.getNameFromIndexSignature(node); + return getNameFromIndexSignature(node); case AST_NODE_TYPES.StaticBlock: return 'static block'; default: @@ -611,7 +616,7 @@ function getLowestRank( return lowestRanks.map(rank => rank.replace(/-/g, ' ')).join(', '); } -export default util.createRule({ +export default createRule({ name: 'member-ordering', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/method-signature-style.ts b/packages/eslint-plugin/src/rules/method-signature-style.ts index ee8ea18ebf83..20a56b54ecbe 100644 --- a/packages/eslint-plugin/src/rules/method-signature-style.ts +++ b/packages/eslint-plugin/src/rules/method-signature-style.ts @@ -1,12 +1,19 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + isClosingParenToken, + isCommaToken, + isOpeningParenToken, + isSemicolonToken, + nullThrows, +} from '../util'; export type Options = [('method' | 'property')?]; export type MessageIds = 'errorMethod' | 'errorProperty'; -export default util.createRule({ +export default createRule({ name: 'method-signature-style', meta: { type: 'suggestion', @@ -53,14 +60,14 @@ export default util.createRule({ ): string { let params = '()'; if (node.params.length > 0) { - const openingParen = util.nullThrows( - sourceCode.getTokenBefore(node.params[0], util.isOpeningParenToken), + const openingParen = nullThrows( + sourceCode.getTokenBefore(node.params[0], isOpeningParenToken), 'Missing opening paren before first parameter', ); - const closingParen = util.nullThrows( + const closingParen = nullThrows( sourceCode.getTokenAfter( node.params[node.params.length - 1], - util.isClosingParenToken, + isClosingParenToken, ), 'Missing closing paren after last parameter', ); @@ -91,7 +98,7 @@ export default util.createRule({ const lastToken = sourceCode.getLastToken(node); if ( lastToken && - (util.isSemicolonToken(lastToken) || util.isCommaToken(lastToken)) + (isSemicolonToken(lastToken) || isCommaToken(lastToken)) ) { return lastToken.value; } diff --git a/packages/eslint-plugin/src/rules/naming-convention-utils/parse-options.ts b/packages/eslint-plugin/src/rules/naming-convention-utils/parse-options.ts index 945777dd7fbd..885c25a8035f 100644 --- a/packages/eslint-plugin/src/rules/naming-convention-utils/parse-options.ts +++ b/packages/eslint-plugin/src/rules/naming-convention-utils/parse-options.ts @@ -1,4 +1,4 @@ -import * as util from '../../util'; +import { getEnumNames } from '../../util'; import { MetaSelectors, Modifiers, @@ -84,7 +84,7 @@ function parseOptions(context: Context): ParsedOptions { .map(opt => normalizeOption(opt)) .reduce((acc, val) => acc.concat(val), []); - const result = util.getEnumNames(Selectors).reduce((acc, k) => { + const result = getEnumNames(Selectors).reduce((acc, k) => { acc[k] = createValidator(k, context, normalizedOptions); return acc; }, {} as ParsedOptions); diff --git a/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts b/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts index 2cb6d9fed62b..3e44a0c34954 100644 --- a/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts +++ b/packages/eslint-plugin/src/rules/naming-convention-utils/schema.ts @@ -1,6 +1,6 @@ import type { JSONSchema } from '@typescript-eslint/utils'; -import * as util from '../../util'; +import { getEnumNames } from '../../util'; import type { IndividualAndMetaSelectorsString, ModifiersString, @@ -18,15 +18,15 @@ const $DEFS: Record = { // enums underscoreOptions: { type: 'string', - enum: util.getEnumNames(UnderscoreOptions), + enum: getEnumNames(UnderscoreOptions), }, predefinedFormats: { type: 'string', - enum: util.getEnumNames(PredefinedFormats), + enum: getEnumNames(PredefinedFormats), }, typeModifiers: { type: 'string', - enum: util.getEnumNames(TypeModifiers), + enum: getEnumNames(TypeModifiers), }, // repeated types @@ -160,10 +160,7 @@ function selectorsSchema(): JSONSchema.JSONSchema4 { type: 'array', items: { type: 'string', - enum: [ - ...util.getEnumNames(MetaSelectors), - ...util.getEnumNames(Selectors), - ], + enum: [...getEnumNames(MetaSelectors), ...getEnumNames(Selectors)], }, additionalItems: false, }, @@ -171,7 +168,7 @@ function selectorsSchema(): JSONSchema.JSONSchema4 { type: 'array', items: { type: 'string', - enum: util.getEnumNames(Modifiers), + enum: getEnumNames(Modifiers), }, additionalItems: false, }, @@ -195,7 +192,7 @@ const SCHEMA: JSONSchema.JSONSchema4 = { items: { oneOf: [ selectorsSchema(), - ...selectorSchema('default', false, util.getEnumNames(Modifiers)), + ...selectorSchema('default', false, getEnumNames(Modifiers)), ...selectorSchema('variableLike', false, ['unused', 'async']), ...selectorSchema('variable', true, [ diff --git a/packages/eslint-plugin/src/rules/naming-convention-utils/validator.ts b/packages/eslint-plugin/src/rules/naming-convention-utils/validator.ts index 4c80a167a0f7..d7ce337b1a11 100644 --- a/packages/eslint-plugin/src/rules/naming-convention-utils/validator.ts +++ b/packages/eslint-plugin/src/rules/naming-convention-utils/validator.ts @@ -2,7 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import type * as ts from 'typescript'; -import * as util from '../../util'; +import { getParserServices } from '../../util'; import type { SelectorsString } from './enums'; import { MetaSelectors, @@ -435,7 +435,7 @@ function isCorrectType( return true; } - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const type = services .getTypeAtLocation(node) diff --git a/packages/eslint-plugin/src/rules/naming-convention.ts b/packages/eslint-plugin/src/rules/naming-convention.ts index d3e52d377cf2..dd287ccadd1c 100644 --- a/packages/eslint-plugin/src/rules/naming-convention.ts +++ b/packages/eslint-plugin/src/rules/naming-convention.ts @@ -3,7 +3,12 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'; import type { ScriptTarget } from 'typescript'; -import * as util from '../util'; +import { + collectUnusedVariables, + createRule, + getParserServices, + requiresQuoting as _requiresQuoting, +} from '../util'; import type { Context, Selector, @@ -47,7 +52,7 @@ const defaultCamelCaseAllTheThingsConfig: Options = [ }, ]; -export default util.createRule({ +export default createRule({ name: 'naming-convention', meta: { docs: { @@ -90,7 +95,7 @@ export default util.createRule({ const validators = parseOptions(context); const compilerOptions = - util.getParserServices(context, true).program?.getCompilerOptions() ?? {}; + getParserServices(context, true).program?.getCompilerOptions() ?? {}; function handleMember( validator: ValidatorFunction, node: @@ -150,7 +155,7 @@ export default util.createRule({ return modifiers; } - const unusedVariables = util.collectUnusedVariables(context); + const unusedVariables = collectUnusedVariables(context); function isUnused( name: string, initialScope: TSESLint.Scope.Scope | null = context.getScope(), @@ -719,7 +724,7 @@ function requiresQuoting( node.type === AST_NODE_TYPES.PrivateIdentifier ? node.name : `${node.value}`; - return util.requiresQuoting(name, target); + return _requiresQuoting(name, target); } export { MessageIds, Options }; diff --git a/packages/eslint-plugin/src/rules/no-array-constructor.ts b/packages/eslint-plugin/src/rules/no-array-constructor.ts index fc71f275d7c3..52fbf7ee0252 100644 --- a/packages/eslint-plugin/src/rules/no-array-constructor.ts +++ b/packages/eslint-plugin/src/rules/no-array-constructor.ts @@ -1,9 +1,9 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, isOptionalCallExpression } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-array-constructor', meta: { type: 'suggestion', @@ -32,7 +32,7 @@ export default util.createRule({ node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === 'Array' && !node.typeArguments && - !util.isOptionalCallExpression(node) + !isOptionalCallExpression(node) ) { context.report({ node, diff --git a/packages/eslint-plugin/src/rules/no-base-to-string.ts b/packages/eslint-plugin/src/rules/no-base-to-string.ts index 9d74c87117c5..eff3753b16c6 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -2,7 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices, getTypeName } from '../util'; enum Usefulness { Always = 'always', @@ -17,7 +17,7 @@ type Options = [ ]; type MessageIds = 'baseToString'; -export default util.createRule({ +export default createRule({ name: 'no-base-to-string', meta: { docs: { @@ -52,7 +52,7 @@ export default util.createRule({ }, ], create(context, [option]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const ignoredTypeNames = option.ignoredTypeNames ?? []; @@ -93,7 +93,7 @@ export default util.createRule({ return Usefulness.Always; } - if (ignoredTypeNames.includes(util.getTypeName(checker, type))) { + if (ignoredTypeNames.includes(getTypeName(checker, type))) { return Usefulness.Always; } @@ -155,10 +155,10 @@ export default util.createRule({ const leftType = services.getTypeAtLocation(node.left); const rightType = services.getTypeAtLocation(node.right); - if (util.getTypeName(checker, leftType) === 'string') { + if (getTypeName(checker, leftType) === 'string') { checkExpression(node.right, rightType); } else if ( - util.getTypeName(checker, rightType) === 'string' && + getTypeName(checker, rightType) === 'string' && node.left.type !== AST_NODE_TYPES.PrivateIdentifier ) { checkExpression(node.left, leftType); diff --git a/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts index 5e91950ed202..7b42603f2ba6 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts @@ -1,9 +1,9 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-confusing-non-null-assertion', meta: { type: 'problem', 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 66ac9e28c512..4a41a66a4922 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -3,7 +3,16 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + isClosingParenToken, + isOpeningParenToken, + isParenthesized, + nullThrows, + NullThrowsReasons, +} from '../util'; export type Options = [ { @@ -22,7 +31,7 @@ export type MessageId = | 'invalidVoidExprWrapVoid' | 'voidExprWrapVoid'; -export default util.createRule({ +export default createRule({ name: 'no-confusing-void-expression', meta: { docs: { @@ -80,8 +89,8 @@ export default util.createRule({ | TSESTree.CallExpression | TSESTree.TaggedTemplateExpression, ): void { - const services = util.getParserServices(context); - const type = util.getConstrainedTypeAtLocation(services, node); + const services = getParserServices(context); + const type = getConstrainedTypeAtLocation(services, node); if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; @@ -121,14 +130,14 @@ export default util.createRule({ const arrowBody = arrowFunction.body; const arrowBodyText = sourceCode.getText(arrowBody); const newArrowBodyText = `{ ${arrowBodyText}; }`; - if (util.isParenthesized(arrowBody, sourceCode)) { + if (isParenthesized(arrowBody, sourceCode)) { const bodyOpeningParen = sourceCode.getTokenBefore( arrowBody, - util.isOpeningParenToken, + isOpeningParenToken, )!; const bodyClosingParen = sourceCode.getTokenAfter( arrowBody, - util.isClosingParenToken, + isClosingParenToken, )!; return fixer.replaceTextRange( [bodyOpeningParen.range[0], bodyClosingParen.range[1]], @@ -220,10 +229,7 @@ export default util.createRule({ * @returns Invalid ancestor node if it was found. `null` otherwise. */ function findInvalidAncestor(node: TSESTree.Node): TSESTree.Node | null { - const parent = util.nullThrows( - node.parent, - util.NullThrowsReasons.MissingParent, - ); + const parent = nullThrows(node.parent, NullThrowsReasons.MissingParent); if (parent.type === AST_NODE_TYPES.SequenceExpression) { if (node !== parent.expressions[parent.expressions.length - 1]) { return null; @@ -282,19 +288,16 @@ export default util.createRule({ /** Checks whether the return statement is the last statement in a function body. */ function isFinalReturn(node: TSESTree.ReturnStatement): boolean { // the parent must be a block - const block = util.nullThrows( - node.parent, - util.NullThrowsReasons.MissingParent, - ); + const block = nullThrows(node.parent, NullThrowsReasons.MissingParent); if (block.type !== AST_NODE_TYPES.BlockStatement) { // e.g. `if (cond) return;` (not in a block) return false; } // the block's parent must be a function - const blockParent = util.nullThrows( + const blockParent = nullThrows( block.parent, - util.NullThrowsReasons.MissingParent, + NullThrowsReasons.MissingParent, ); if ( ![ @@ -327,9 +330,9 @@ export default util.createRule({ node: TSESTree.Expression, sourceCode: Readonly, ): boolean { - const startToken = util.nullThrows( + const startToken = nullThrows( sourceCode.getFirstToken(node), - util.NullThrowsReasons.MissingToken('first token', node.type), + NullThrowsReasons.MissingToken('first token', node.type), ); return ['(', '[', '`'].includes(startToken.value); 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 95689cae513c..09c734a75585 100644 --- a/packages/eslint-plugin/src/rules/no-dupe-class-members.ts +++ b/packages/eslint-plugin/src/rules/no-dupe-class-members.ts @@ -1,15 +1,19 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-dupe-class-members'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'no-dupe-class-members', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-duplicate-enum-values.ts b/packages/eslint-plugin/src/rules/no-duplicate-enum-values.ts index 8aeb1c4200b3..f5a58ce14f12 100644 --- a/packages/eslint-plugin/src/rules/no-duplicate-enum-values.ts +++ b/packages/eslint-plugin/src/rules/no-duplicate-enum-values.ts @@ -1,9 +1,9 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-duplicate-enum-values', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-duplicate-type-constituents.ts b/packages/eslint-plugin/src/rules/no-duplicate-type-constituents.ts index c6e31acf5864..316259a064a5 100644 --- a/packages/eslint-plugin/src/rules/no-duplicate-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/no-duplicate-type-constituents.ts @@ -2,7 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import type { Type } from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices } from '../util'; export type Options = [ { @@ -66,7 +66,7 @@ const isSameAstNode = (actualNode: unknown, expectedNode: unknown): boolean => { return false; }; -export default util.createRule({ +export default createRule({ name: 'no-duplicate-type-constituents', meta: { type: 'suggestion', @@ -102,7 +102,7 @@ export default util.createRule({ }, ], create(context, [{ ignoreIntersections, ignoreUnions }]) { - const parserServices = util.getParserServices(context); + const parserServices = getParserServices(context); const checker = parserServices.program.getTypeChecker(); function checkDuplicate( diff --git a/packages/eslint-plugin/src/rules/no-dynamic-delete.ts b/packages/eslint-plugin/src/rules/no-dynamic-delete.ts index 0d1127f8a923..cf113350701b 100644 --- a/packages/eslint-plugin/src/rules/no-dynamic-delete.ts +++ b/packages/eslint-plugin/src/rules/no-dynamic-delete.ts @@ -2,9 +2,9 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-dynamic-delete', meta: { docs: { diff --git a/packages/eslint-plugin/src/rules/no-empty-function.ts b/packages/eslint-plugin/src/rules/no-empty-function.ts index e77981eab301..363b393e9d27 100644 --- a/packages/eslint-plugin/src/rules/no-empty-function.ts +++ b/packages/eslint-plugin/src/rules/no-empty-function.ts @@ -2,15 +2,19 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, deepMerge } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-empty-function'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; -const schema = util.deepMerge( +const schema = deepMerge( // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- https://github.com/microsoft/TypeScript/issues/17002 Array.isArray(baseRule.meta.schema) ? baseRule.meta.schema[0] @@ -42,7 +46,7 @@ const schema = util.deepMerge( }, ) as unknown as JSONSchema4; -export default util.createRule({ +export default createRule({ name: 'no-empty-function', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index 12499f3b95c6..2ca3a27fdf28 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -2,7 +2,7 @@ import { ScopeType } from '@typescript-eslint/scope-manager'; import type { TSESLint } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, isDefinitionFile } from '../util'; type Options = [ { @@ -11,7 +11,7 @@ type Options = [ ]; type MessageIds = 'noEmpty' | 'noEmptyWithSuper'; -export default util.createRule({ +export default createRule({ name: 'no-empty-interface', meta: { type: 'suggestion', @@ -84,7 +84,7 @@ export default util.createRule({ ); const isInAmbientDeclaration = !!( - util.isDefinitionFile(filename) && + isDefinitionFile(filename) && scope.type === ScopeType.tsModule && scope.block.declare ); diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index fd2ddeefbe2b..ccf4cf47fb0f 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -1,7 +1,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; export type Options = [ { @@ -11,7 +11,7 @@ export type Options = [ ]; export type MessageIds = 'suggestNever' | 'suggestUnknown' | 'unexpectedAny'; -export default util.createRule({ +export default createRule({ name: 'no-explicit-any', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts index 082c3d212a69..ee1858fe7d95 100644 --- a/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts @@ -1,8 +1,8 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-extra-non-null-assertion', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-extra-parens.ts b/packages/eslint-plugin/src/rules/no-extra-parens.ts index 5d26f8a5efb7..ab708faa83db 100644 --- a/packages/eslint-plugin/src/rules/no-extra-parens.ts +++ b/packages/eslint-plugin/src/rules/no-extra-parens.ts @@ -4,15 +4,19 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, isOpeningParenToken, isTypeAssertion } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-extra-parens'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'no-extra-parens', meta: { type: 'layout', @@ -36,8 +40,8 @@ export default util.createRule({ const rule = rules.BinaryExpression as (n: typeof node) => void; // makes the rule think it should skip the left or right - const isLeftTypeAssertion = util.isTypeAssertion(node.left); - const isRightTypeAssertion = util.isTypeAssertion(node.right); + const isLeftTypeAssertion = isTypeAssertion(node.left); + const isRightTypeAssertion = isTypeAssertion(node.right); if (isLeftTypeAssertion && isRightTypeAssertion) { return; // ignore } @@ -67,7 +71,7 @@ export default util.createRule({ ): void { const rule = rules.CallExpression as (n: typeof node) => void; - if (util.isTypeAssertion(node.callee)) { + if (isTypeAssertion(node.callee)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped return rule({ ...node, @@ -81,8 +85,8 @@ export default util.createRule({ if ( node.arguments.length === 1 && // is there any opening parenthesis in type arguments - sourceCode.getTokenAfter(node.callee, util.isOpeningParenToken) !== - sourceCode.getTokenBefore(node.arguments[0], util.isOpeningParenToken) + sourceCode.getTokenAfter(node.callee, isOpeningParenToken) !== + sourceCode.getTokenBefore(node.arguments[0], isOpeningParenToken) ) { return rule({ ...node, @@ -102,7 +106,7 @@ export default util.createRule({ ): void { const rule = rules.UnaryExpression as (n: typeof node) => void; - if (util.isTypeAssertion(node.argument)) { + if (isTypeAssertion(node.argument)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped return rule({ ...node, @@ -119,13 +123,13 @@ export default util.createRule({ const overrides: TSESLint.RuleListener = { // ArrayExpression ArrowFunctionExpression(node) { - if (!util.isTypeAssertion(node.body)) { + if (!isTypeAssertion(node.body)) { return rules.ArrowFunctionExpression(node); } }, // AssignmentExpression AwaitExpression(node) { - if (util.isTypeAssertion(node.argument)) { + if (isTypeAssertion(node.argument)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped return rules.AwaitExpression({ ...node, @@ -165,7 +169,7 @@ export default util.createRule({ }, ConditionalExpression(node) { // reduces the precedence of the node so the rule thinks it needs to be wrapped - if (util.isTypeAssertion(node.test)) { + if (isTypeAssertion(node.test)) { return rules.ConditionalExpression({ ...node, test: { @@ -174,7 +178,7 @@ export default util.createRule({ }, }); } - if (util.isTypeAssertion(node.consequent)) { + if (isTypeAssertion(node.consequent)) { return rules.ConditionalExpression({ ...node, consequent: { @@ -183,7 +187,7 @@ export default util.createRule({ }, }); } - if (util.isTypeAssertion(node.alternate)) { + if (isTypeAssertion(node.alternate)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped return rules.ConditionalExpression({ ...node, @@ -199,19 +203,19 @@ export default util.createRule({ // ForIn and ForOf are guarded by eslint version ForStatement(node) { // make the rule skip the piece by removing it entirely - if (node.init && util.isTypeAssertion(node.init)) { + if (node.init && isTypeAssertion(node.init)) { return rules.ForStatement({ ...node, init: null, }); } - if (node.test && util.isTypeAssertion(node.test)) { + if (node.test && isTypeAssertion(node.test)) { return rules.ForStatement({ ...node, test: null, }); } - if (node.update && util.isTypeAssertion(node.update)) { + if (node.update && isTypeAssertion(node.update)) { return rules.ForStatement({ ...node, update: null, @@ -221,14 +225,14 @@ export default util.createRule({ return rules.ForStatement(node); }, 'ForStatement > *.init:exit'(node: TSESTree.Node) { - if (!util.isTypeAssertion(node)) { + if (!isTypeAssertion(node)) { return rules['ForStatement > *.init:exit'](node); } }, // IfStatement LogicalExpression: binaryExp, MemberExpression(node) { - if (util.isTypeAssertion(node.object)) { + if (isTypeAssertion(node.object)) { // reduces the precedence of the node so the rule thinks it needs to be wrapped return rules.MemberExpression({ ...node, @@ -246,18 +250,18 @@ export default util.createRule({ // ReturnStatement // SequenceExpression SpreadElement(node) { - if (!util.isTypeAssertion(node.argument)) { + if (!isTypeAssertion(node.argument)) { return rules.SpreadElement(node); } }, SwitchCase(node) { - if (node.test && !util.isTypeAssertion(node.test)) { + if (node.test && !isTypeAssertion(node.test)) { return rules.SwitchCase(node); } }, // SwitchStatement ThrowStatement(node) { - if (node.argument && !util.isTypeAssertion(node.argument)) { + if (node.argument && !isTypeAssertion(node.argument)) { return rules.ThrowStatement(node); } }, @@ -267,14 +271,14 @@ export default util.createRule({ // WhileStatement // WithStatement - i'm not going to even bother implementing this terrible and never used feature YieldExpression(node) { - if (node.argument && !util.isTypeAssertion(node.argument)) { + if (node.argument && !isTypeAssertion(node.argument)) { return rules.YieldExpression(node); } }, }; if (rules.ForInStatement && rules.ForOfStatement) { overrides.ForInStatement = function (node): void { - if (util.isTypeAssertion(node.right)) { + if (isTypeAssertion(node.right)) { // as of 7.20.0 there's no way to skip checking the right of the ForIn // so just don't validate it at all return; @@ -283,7 +287,7 @@ export default util.createRule({ return rules.ForInStatement(node); }; overrides.ForOfStatement = function (node): void { - if (util.isTypeAssertion(node.right)) { + if (isTypeAssertion(node.right)) { // makes the rule skip checking of the right return rules.ForOfStatement({ ...node, @@ -301,7 +305,7 @@ export default util.createRule({ overrides['ForInStatement, ForOfStatement'] = function ( node: TSESTree.ForInStatement | TSESTree.ForOfStatement, ): void { - if (util.isTypeAssertion(node.right)) { + if (isTypeAssertion(node.right)) { // makes the rule skip checking of the right return rules['ForInStatement, ForOfStatement']({ ...node, diff --git a/packages/eslint-plugin/src/rules/no-extra-semi.ts b/packages/eslint-plugin/src/rules/no-extra-semi.ts index d2860771c53b..84903111bb71 100644 --- a/packages/eslint-plugin/src/rules/no-extra-semi.ts +++ b/packages/eslint-plugin/src/rules/no-extra-semi.ts @@ -1,12 +1,16 @@ -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-extra-semi'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'no-extra-semi', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-extraneous-class.ts b/packages/eslint-plugin/src/rules/no-extraneous-class.ts index 21dda4c686dd..009da2a21a75 100644 --- a/packages/eslint-plugin/src/rules/no-extraneous-class.ts +++ b/packages/eslint-plugin/src/rules/no-extraneous-class.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Options = [ { @@ -13,7 +13,7 @@ type Options = [ ]; type MessageIds = 'empty' | 'onlyConstructor' | 'onlyStatic'; -export default util.createRule({ +export default createRule({ name: 'no-extraneous-class', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-floating-promises.ts b/packages/eslint-plugin/src/rules/no-floating-promises.ts index bd1aadaeab2f..066469c3507d 100644 --- a/packages/eslint-plugin/src/rules/no-floating-promises.ts +++ b/packages/eslint-plugin/src/rules/no-floating-promises.ts @@ -3,8 +3,12 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; -import { OperatorPrecedence } from '../util'; +import { + createRule, + getOperatorPrecedence, + getParserServices, + OperatorPrecedence, +} from '../util'; type Options = [ { @@ -31,7 +35,7 @@ const messageBaseVoid = const messageRejectionHandler = 'A rejection handler that is not a function will be ignored.'; -export default util.createRule({ +export default createRule({ name: 'no-floating-promises', meta: { docs: { @@ -78,7 +82,7 @@ export default util.createRule({ ], create(context, [options]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); return { @@ -171,7 +175,7 @@ export default util.createRule({ const operator = ts.isBinaryExpression(node) ? node.operatorToken.kind : ts.SyntaxKind.Unknown; - const nodePrecedence = util.getOperatorPrecedence(node.kind, operator); + const nodePrecedence = getOperatorPrecedence(node.kind, operator); return nodePrecedence > OperatorPrecedence.Unary; } diff --git a/packages/eslint-plugin/src/rules/no-for-in-array.ts b/packages/eslint-plugin/src/rules/no-for-in-array.ts index ab6e98321656..75a04de8b9c0 100644 --- a/packages/eslint-plugin/src/rules/no-for-in-array.ts +++ b/packages/eslint-plugin/src/rules/no-for-in-array.ts @@ -1,8 +1,13 @@ import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + isTypeArrayTypeOrUnionOfArrayTypes, +} from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-for-in-array', meta: { docs: { @@ -21,13 +26,13 @@ export default util.createRule({ create(context) { return { ForInStatement(node): void { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); - const type = util.getConstrainedTypeAtLocation(services, node.right); + const type = getConstrainedTypeAtLocation(services, node.right); if ( - util.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || + isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || (type.flags & ts.TypeFlags.StringLike) !== 0 ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index 0560d7647c42..eede26dce3cd 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -3,7 +3,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices } from '../util'; const FUNCTION_CONSTRUCTOR = 'Function'; const GLOBAL_CANDIDATES = new Set(['global', 'window', 'globalThis']); @@ -14,7 +14,7 @@ const EVAL_LIKE_METHODS = new Set([ 'execScript', ]); -export default util.createRule({ +export default createRule({ name: 'no-implied-eval', meta: { docs: { @@ -33,7 +33,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); function getCalleeName( diff --git a/packages/eslint-plugin/src/rules/no-import-type-side-effects.ts b/packages/eslint-plugin/src/rules/no-import-type-side-effects.ts index 0e814a0ca48d..8501c9fd4aea 100644 --- a/packages/eslint-plugin/src/rules/no-import-type-side-effects.ts +++ b/packages/eslint-plugin/src/rules/no-import-type-side-effects.ts @@ -1,12 +1,18 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + isImportKeyword, + isTypeKeyword, + nullThrows, + NullThrowsReasons, +} from '../util'; type Options = []; type MessageIds = 'useTopLevelQualifier'; -export default util.createRule({ +export default createRule({ name: 'no-import-type-side-effects', meta: { type: 'problem', @@ -49,9 +55,9 @@ export default util.createRule({ fix(fixer) { const fixes: TSESLint.RuleFix[] = []; for (const specifier of specifiers) { - const qualifier = util.nullThrows( - sourceCode.getFirstToken(specifier, util.isTypeKeyword), - util.NullThrowsReasons.MissingToken( + const qualifier = nullThrows( + sourceCode.getFirstToken(specifier, isTypeKeyword), + NullThrowsReasons.MissingToken( 'type keyword', 'import specifier', ), @@ -64,9 +70,9 @@ export default util.createRule({ ); } - const importKeyword = util.nullThrows( - sourceCode.getFirstToken(node, util.isImportKeyword), - util.NullThrowsReasons.MissingToken('import keyword', 'import'), + const importKeyword = nullThrows( + sourceCode.getFirstToken(node, isImportKeyword), + NullThrowsReasons.MissingToken('import keyword', 'import'), ); fixes.push(fixer.insertTextAfter(importKeyword, ' type')); diff --git a/packages/eslint-plugin/src/rules/no-inferrable-types.ts b/packages/eslint-plugin/src/rules/no-inferrable-types.ts index f63beda74401..15f88ca85c07 100644 --- a/packages/eslint-plugin/src/rules/no-inferrable-types.ts +++ b/packages/eslint-plugin/src/rules/no-inferrable-types.ts @@ -2,7 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Options = [ { @@ -12,7 +12,7 @@ type Options = [ ]; type MessageIds = 'noInferrableType'; -export default util.createRule({ +export default createRule({ name: 'no-inferrable-types', meta: { type: 'suggestion', 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 4808a439f5a3..fa849d8ac915 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; interface Options { allowInGenericTypeArguments?: string[] | boolean; @@ -16,7 +16,7 @@ type MessageIds = | 'invalidVoidNotReturnOrThisParamOrGeneric' | 'invalidVoidUnionConstituent'; -export default util.createRule<[Options], MessageIds>({ +export default createRule<[Options], MessageIds>({ name: 'no-invalid-void-type', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-loop-func.ts b/packages/eslint-plugin/src/rules/no-loop-func.ts index f4e4b50825c9..03f7662f9e33 100644 --- a/packages/eslint-plugin/src/rules/no-loop-func.ts +++ b/packages/eslint-plugin/src/rules/no-loop-func.ts @@ -1,15 +1,19 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-loop-func'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'no-loop-func', meta: { type: 'suggestion', 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 8a07f975ab15..ed3747884abd 100644 --- a/packages/eslint-plugin/src/rules/no-loss-of-precision.ts +++ b/packages/eslint-plugin/src/rules/no-loss-of-precision.ts @@ -1,16 +1,18 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { maybeGetESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = maybeGetESLintCoreRule('no-loss-of-precision'); -type Options = util.InferOptionsTypeFromRule>; -type MessageIds = util.InferMessageIdsTypeFromRule< - NonNullable ->; +type Options = InferOptionsTypeFromRule>; +type MessageIds = InferMessageIdsTypeFromRule>; -export default util.createRule({ +export default createRule({ name: 'no-loss-of-precision', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 92a03c9078d4..67083f27e287 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -2,17 +2,20 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, deepMerge } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-magic-numbers'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; // Extend base schema with additional property to ignore TS numeric literal types -const schema = util.deepMerge( - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- https://github.com/microsoft/TypeScript/issues/17002 +const schema = deepMerge( Array.isArray(baseRule.meta.schema) ? baseRule.meta.schema[0] : baseRule.meta.schema, @@ -34,7 +37,7 @@ const schema = util.deepMerge( }, ) as unknown as JSONSchema4; -export default util.createRule({ +export default createRule({ name: 'no-magic-numbers', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-meaningless-void-operator.ts b/packages/eslint-plugin/src/rules/no-meaningless-void-operator.ts index 524c54387889..0b371f9cf349 100644 --- a/packages/eslint-plugin/src/rules/no-meaningless-void-operator.ts +++ b/packages/eslint-plugin/src/rules/no-meaningless-void-operator.ts @@ -3,7 +3,7 @@ import { ESLintUtils } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule } from '../util'; type Options = [ { @@ -11,10 +11,7 @@ type Options = [ }, ]; -export default util.createRule< - Options, - 'meaninglessVoidOperator' | 'removeVoid' ->({ +export default createRule({ name: 'no-meaningless-void-operator', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-misused-new.ts b/packages/eslint-plugin/src/rules/no-misused-new.ts index 41df0cb5f997..049101a110e0 100644 --- a/packages/eslint-plugin/src/rules/no-misused-new.ts +++ b/packages/eslint-plugin/src/rules/no-misused-new.ts @@ -1,9 +1,9 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-misused-new', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index a5fe0721b88d..7fd6fb9ca71c 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -3,7 +3,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices, getTypeArguments } from '../util'; type Options = [ { @@ -58,7 +58,7 @@ function parseChecksVoidReturn( } } -export default util.createRule({ +export default createRule({ name: 'no-misused-promises', meta: { docs: { @@ -121,7 +121,7 @@ export default util.createRule({ ], create(context, [{ checksConditionals, checksVoidReturn, checksSpreads }]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const checkedNodes = new Set(); @@ -556,7 +556,7 @@ function voidFunctionArguments( // Unwrap 'Array' to 'MaybeVoidFunction', // so that we'll handle it in the same way as a non-rest // 'param: MaybeVoidFunction' - type = util.getTypeArguments(type, checker)[0]; + type = getTypeArguments(type, checker)[0]; for (let i = index; i < node.arguments.length; i++) { checkThenableOrVoidArgument( checker, @@ -570,7 +570,7 @@ function voidFunctionArguments( } else if (checker.isTupleType(type)) { // Check each type in the tuple - for example, [boolean, () => void] would // add the index of the second tuple parameter to 'voidReturnIndices' - const typeArgs = util.getTypeArguments(type, checker); + const typeArgs = getTypeArguments(type, checker); for ( let i = index; i < node.arguments.length && i - index < typeArgs.length; diff --git a/packages/eslint-plugin/src/rules/no-mixed-enums.ts b/packages/eslint-plugin/src/rules/no-mixed-enums.ts index 33ad352b1b69..71344fa5a689 100644 --- a/packages/eslint-plugin/src/rules/no-mixed-enums.ts +++ b/packages/eslint-plugin/src/rules/no-mixed-enums.ts @@ -5,7 +5,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices } from '../util'; enum AllowedType { Number, @@ -13,7 +13,7 @@ enum AllowedType { Unknown, } -export default util.createRule({ +export default createRule({ name: 'no-mixed-enums', meta: { docs: { @@ -29,7 +29,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const parserServices = util.getParserServices(context); + const parserServices = getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); interface CollectedDefinitions { diff --git a/packages/eslint-plugin/src/rules/no-namespace.ts b/packages/eslint-plugin/src/rules/no-namespace.ts index 145ddc3ad16b..516225271956 100644 --- a/packages/eslint-plugin/src/rules/no-namespace.ts +++ b/packages/eslint-plugin/src/rules/no-namespace.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, isDefinitionFile } from '../util'; type Options = [ { @@ -11,7 +11,7 @@ type Options = [ ]; type MessageIds = 'moduleSyntaxIsPreferred'; -export default util.createRule({ +export default createRule({ name: 'no-namespace', meta: { type: 'suggestion', @@ -68,7 +68,7 @@ export default util.createRule({ ): void { if ( node.parent.type === AST_NODE_TYPES.TSModuleDeclaration || - (allowDefinitionFiles && util.isDefinitionFile(filename)) || + (allowDefinitionFiles && isDefinitionFile(filename)) || (allowDeclarations && isDeclaration(node)) ) { return; diff --git a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts index a79fa4062b1f..44d540cd44ea 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts @@ -3,7 +3,7 @@ import { DefinitionType } from '@typescript-eslint/scope-manager'; import type { TSESLint } from '@typescript-eslint/utils'; import { ASTUtils, TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, nullThrows, NullThrowsReasons } from '../util'; function hasAssignmentBeforeNode( variable: TSESLint.Scope.Variable, @@ -31,7 +31,7 @@ function isDefinitionWithAssignment(definition: Definition): boolean { ); } -export default util.createRule({ +export default createRule({ name: 'no-non-null-asserted-nullish-coalescing', meta: { type: 'problem', @@ -85,15 +85,12 @@ export default util.createRule({ { messageId: 'suggestRemovingNonNull', fix(fixer): TSESLint.RuleFix { - const exclamationMark = util.nullThrows( + const exclamationMark = nullThrows( sourceCode.getLastToken( node, ASTUtils.isNonNullAssertionPunctuator, ), - util.NullThrowsReasons.MissingToken( - '!', - 'Non-null Assertion', - ), + NullThrowsReasons.MissingToken('!', 'Non-null Assertion'), ); return fixer.remove(exclamationMark); }, diff --git a/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts b/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts index 3939fbdebb2a..efc8fc26cf5a 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts @@ -1,8 +1,8 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-non-null-asserted-optional-chain', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-non-null-assertion.ts index ba8b88158def..6883b908bb54 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-assertion.ts @@ -1,11 +1,11 @@ import type { TSESLint } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, isNonNullAssertionPunctuator } from '../util'; type MessageIds = 'noNonNull' | 'suggestOptionalChain'; -export default util.createRule<[], MessageIds>({ +export default createRule<[], MessageIds>({ name: 'no-non-null-assertion', meta: { type: 'problem', @@ -34,7 +34,7 @@ export default util.createRule<[], MessageIds>({ return (fixer: TSESLint.RuleFixer): TSESLint.RuleFix | null => { const operator = sourceCode.getTokenAfter( node.expression, - util.isNonNullAssertionPunctuator, + isNonNullAssertionPunctuator, ); if (operator) { return fixer.replaceText(operator, replacement); @@ -47,7 +47,7 @@ export default util.createRule<[], MessageIds>({ return (fixer: TSESLint.RuleFixer): TSESLint.RuleFix | null => { const operator = sourceCode.getTokenAfter( node.expression, - util.isNonNullAssertionPunctuator, + isNonNullAssertionPunctuator, ); if (operator) { return fixer.remove(operator); diff --git a/packages/eslint-plugin/src/rules/no-redeclare.ts b/packages/eslint-plugin/src/rules/no-redeclare.ts index 1f47b575c813..296dc4a6d14f 100644 --- a/packages/eslint-plugin/src/rules/no-redeclare.ts +++ b/packages/eslint-plugin/src/rules/no-redeclare.ts @@ -2,7 +2,7 @@ import { ScopeType } from '@typescript-eslint/scope-manager'; import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, getNameLocationInGlobalDirectiveComment } from '../util'; type MessageIds = 'redeclared' | 'redeclaredAsBuiltin' | 'redeclaredBySyntax'; type Options = [ @@ -12,7 +12,7 @@ type Options = [ }, ]; -export default util.createRule({ +export default createRule({ name: 'no-redeclare', meta: { type: 'suggestion', @@ -91,7 +91,7 @@ export default util.createRule({ yield { type: 'comment', node: comment, - loc: util.getNameLocationInGlobalDirectiveComment( + loc: getNameLocationInGlobalDirectiveComment( sourceCode, comment, variable.name, diff --git a/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts b/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts index e70637256bfd..f38d6c6ad6f1 100644 --- a/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts @@ -2,7 +2,18 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + arrayGroupByToMap, + createRule, + getParserServices, + isFunction, + isFunctionType, + isTypeAnyType, + isTypeBigIntLiteralType, + isTypeNeverType, + isTypeTemplateLiteralType, + isTypeUnknownType, +} from '../util'; const literalToPrimitiveTypeFlags = { [ts.TypeFlags.BigIntLiteral]: ts.TypeFlags.BigInt, @@ -82,7 +93,7 @@ function describeLiteralType(type: ts.Type): string { return JSON.stringify(type.value); } - if (util.isTypeBigIntLiteralType(type)) { + if (isTypeBigIntLiteralType(type)) { return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`; } @@ -91,23 +102,23 @@ function describeLiteralType(type: ts.Type): string { return type.value.toString(); } - if (util.isTypeAnyType(type)) { + if (isTypeAnyType(type)) { return 'any'; } - if (util.isTypeNeverType(type)) { + if (isTypeNeverType(type)) { return 'never'; } - if (util.isTypeUnknownType(type)) { + if (isTypeUnknownType(type)) { return 'unknown'; } - if (util.isTypeTemplateLiteralType(type)) { + if (isTypeTemplateLiteralType(type)) { return 'template literal type'; } - if (util.isTypeBigIntLiteralType(type)) { + if (isTypeBigIntLiteralType(type)) { return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`; } @@ -160,8 +171,7 @@ function describeLiteralTypeNode(typeNode: TSESTree.TypeNode): string { function isNodeInsideReturnType(node: TSESTree.TSUnionType): boolean { return !!( node.parent?.type === AST_NODE_TYPES.TSTypeAnnotation && - (util.isFunctionType(node.parent.parent) || - util.isFunction(node.parent.parent)) + (isFunctionType(node.parent.parent) || isFunction(node.parent.parent)) ); } @@ -177,7 +187,7 @@ function unionTypePartsUnlessBoolean(type: ts.Type): ts.Type[] { : tsutils.unionTypeParts(type); } -export default util.createRule({ +export default createRule({ name: 'no-redundant-type-constituents', meta: { docs: { @@ -197,7 +207,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const typesCache = new Map(); function getTypeNodeTypePartFlags( @@ -438,7 +448,7 @@ export default util.createRule({ // group those literals by their primitive type, // then report each primitive type with all its literals for (const [typeNode, typeFlagsWithText] of overriddenTypeNodes) { - const grouped = util.arrayGroupByToMap( + const grouped = arrayGroupByToMap( typeFlagsWithText, pair => pair.primitiveTypeFlag, ); diff --git a/packages/eslint-plugin/src/rules/no-require-imports.ts b/packages/eslint-plugin/src/rules/no-require-imports.ts index 2f9310b38fcd..32a365436b96 100644 --- a/packages/eslint-plugin/src/rules/no-require-imports.ts +++ b/packages/eslint-plugin/src/rules/no-require-imports.ts @@ -1,9 +1,9 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { ASTUtils } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-require-imports', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-shadow.ts b/packages/eslint-plugin/src/rules/no-shadow.ts index e8dc7a260f8d..b26e8b4a957f 100644 --- a/packages/eslint-plugin/src/rules/no-shadow.ts +++ b/packages/eslint-plugin/src/rules/no-shadow.ts @@ -6,7 +6,7 @@ import { DefinitionType, ScopeType } from '@typescript-eslint/scope-manager'; import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, ASTUtils } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type MessageIds = 'noShadow' | 'noShadowGlobal'; type Options = [ @@ -26,7 +26,7 @@ const allowedFunctionVariableDefTypes = new Set([ AST_NODE_TYPES.TSMethodSignature, ]); -export default util.createRule({ +export default createRule({ name: 'no-shadow', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-this-alias.ts b/packages/eslint-plugin/src/rules/no-this-alias.ts index 57a326e2e808..ece937cff3df 100644 --- a/packages/eslint-plugin/src/rules/no-this-alias.ts +++ b/packages/eslint-plugin/src/rules/no-this-alias.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Options = [ { @@ -11,7 +11,7 @@ type Options = [ ]; type MessageIds = 'thisAssignment' | 'thisDestructure'; -export default util.createRule({ +export default createRule({ name: 'no-this-alias', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index 55145507d657..f1129c252036 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -2,7 +2,12 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getParserServices, + isTypeAnyType, + isTypeUnknownType, +} from '../util'; type MessageIds = 'object' | 'undef'; @@ -13,7 +18,7 @@ type Options = [ }, ]; -export default util.createRule({ +export default createRule({ name: 'no-throw-literal', meta: { type: 'problem', @@ -49,7 +54,7 @@ export default util.createRule({ }, ], create(context, [options]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); function isErrorLike(type: ts.Type): boolean { @@ -101,11 +106,11 @@ export default util.createRule({ return; } - if (options.allowThrowingAny && util.isTypeAnyType(type)) { + if (options.allowThrowingAny && isTypeAnyType(type)) { return; } - if (options.allowThrowingUnknown && util.isTypeUnknownType(type)) { + if (options.allowThrowingUnknown && isTypeUnknownType(type)) { return; } diff --git a/packages/eslint-plugin/src/rules/no-type-alias.ts b/packages/eslint-plugin/src/rules/no-type-alias.ts index cc568a6fa9db..b72c1f8b991a 100644 --- a/packages/eslint-plugin/src/rules/no-type-alias.ts +++ b/packages/eslint-plugin/src/rules/no-type-alias.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Values = | 'always' @@ -32,7 +32,7 @@ interface TypeWithLabel { compositionType: CompositionType | null; } -export default util.createRule({ +export default createRule({ name: 'no-type-alias', meta: { deprecated: true, diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index d0aba2defc7a..9a25eeb5f415 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -3,7 +3,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices, isStrongPrecedenceNode } from '../util'; type MessageIds = | 'comparingNullableToFalse' @@ -29,7 +29,7 @@ interface BooleanComparisonWithTypeInformation extends BooleanComparison { expressionIsNullableBoolean: boolean; } -export default util.createRule({ +export default createRule({ name: 'no-unnecessary-boolean-literal-compare', meta: { docs: { @@ -78,7 +78,7 @@ export default util.createRule({ }, ], create(context, [options]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const sourceCode = context.getSourceCode(); function getBooleanComparison( @@ -240,7 +240,7 @@ export default util.createRule({ yield fixer.insertTextBefore(mutatedNode, '!'); // if the expression `exp` is not a strong precedence node, wrap it in parentheses - if (!util.isStrongPrecedenceNode(comparison.expression)) { + if (!isStrongPrecedenceNode(comparison.expression)) { yield fixer.insertTextBefore(mutatedNode, '('); yield fixer.insertTextAfter(mutatedNode, ')'); } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index c1c558dab8a0..56286b8510cb 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -3,9 +3,9 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-unnecessary-qualifier', meta: { docs: { @@ -24,7 +24,7 @@ export default util.createRule({ create(context) { const namespacesInScope: ts.Node[] = []; let currentFailedNamespaceExpression: TSESTree.Node | null = null; - const services = util.getParserServices(context); + const services = getParserServices(context); const esTreeNodeToTSNodeMap = services.esTreeNodeToTSNodeMap; const checker = services.program.getTypeChecker(); const sourceCode = context.getSourceCode(); diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts index cb3b881e8feb..d766257d6c6c 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -2,8 +2,13 @@ import type { TSESTree } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; -import { findFirstResult } from '../util'; +import { + createRule, + findFirstResult, + getParserServices, + getTypeArguments, + isTypeReferenceType, +} from '../util'; type ParameterCapableTSNode = | ts.CallExpression @@ -18,7 +23,7 @@ type ParameterCapableTSNode = type MessageIds = 'unnecessaryTypeParameter'; -export default util.createRule<[], MessageIds>({ +export default createRule<[], MessageIds>({ name: 'no-unnecessary-type-arguments', meta: { docs: { @@ -36,17 +41,17 @@ export default util.createRule<[], MessageIds>({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); function getTypeForComparison(type: ts.Type): { type: ts.Type; typeArguments: readonly ts.Type[]; } { - if (util.isTypeReferenceType(type)) { + if (isTypeReferenceType(type)) { return { type: type.target, - typeArguments: util.getTypeArguments(type, checker), + typeArguments: getTypeArguments(type, checker), }; } return { diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts index d466b59fe076..ba8ab57f1efb 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -3,7 +3,14 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getContextualType, + getDeclaration, + getParserServices, + isNullableType, +} from '../util'; type Options = [ { @@ -12,7 +19,7 @@ type Options = [ ]; type MessageIds = 'contextuallyUnnecessary' | 'unnecessaryAssertion'; -export default util.createRule({ +export default createRule({ name: 'no-unnecessary-type-assertion', meta: { docs: { @@ -48,7 +55,7 @@ export default util.createRule({ defaultOptions: [{}], create(context, [options]) { const sourceCode = context.getSourceCode(); - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const compilerOptions = services.program.getCompilerOptions(); @@ -87,7 +94,7 @@ export default util.createRule({ * Returns true if there's a chance the variable has been used before a value has been assigned to it */ function isPossiblyUsedBeforeAssigned(node: TSESTree.Expression): boolean { - const declaration = util.getDeclaration(services, node); + const declaration = getDeclaration(services, node); if (!declaration) { // don't know what the declaration is for some reason, so just assume the worst return true; @@ -109,7 +116,7 @@ export default util.createRule({ ) { // check if the defined variable type has changed since assignment const declarationType = checker.getTypeFromTypeNode(declaration.type); - const type = util.getConstrainedTypeAtLocation(services, node); + const type = getConstrainedTypeAtLocation(services, node); if (declarationType === type) { // possibly used before assigned, so just skip it // better to false negative and skip it, than false positive and fix to compile erroring code @@ -157,12 +164,9 @@ export default util.createRule({ const originalNode = services.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation( - services, - node.expression, - ); + const type = getConstrainedTypeAtLocation(services, node.expression); - if (!util.isNullableType(type)) { + if (!isNullableType(type)) { if (isPossiblyUsedBeforeAssigned(node.expression)) { return; } @@ -181,24 +185,24 @@ export default util.createRule({ // we know it's a nullable type // so figure out if the variable is used in a place that accepts nullable types - const contextualType = util.getContextualType(checker, originalNode); + const contextualType = getContextualType(checker, originalNode); if (contextualType) { // in strict mode you can't assign null to undefined, so we have to make sure that // the two types share a nullable type - const typeIncludesUndefined = util.isTypeFlagSet( + const typeIncludesUndefined = tsutils.isTypeFlagSet( type, ts.TypeFlags.Undefined, ); - const typeIncludesNull = util.isTypeFlagSet( + const typeIncludesNull = tsutils.isTypeFlagSet( type, ts.TypeFlags.Null, ); - const contextualTypeIncludesUndefined = util.isTypeFlagSet( + const contextualTypeIncludesUndefined = tsutils.isTypeFlagSet( contextualType, ts.TypeFlags.Undefined, ); - const contextualTypeIncludesNull = util.isTypeFlagSet( + const contextualTypeIncludesNull = tsutils.isTypeFlagSet( contextualType, ts.TypeFlags.Null, ); diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-constraint.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-constraint.ts index 7ca1106f7174..21a98de67a45 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-constraint.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-constraint.ts @@ -3,7 +3,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { extname } from 'path'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule } from '../util'; type MakeRequired = Omit & { [K in Key]-?: NonNullable; @@ -13,7 +13,7 @@ type TypeParameterWithConstraint = MakeRequired< 'constraint' >; -export default util.createRule({ +export default createRule({ name: 'no-unnecessary-type-constraint', meta: { docs: { diff --git a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts index dab8c33be89c..fe74d1360969 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts @@ -2,7 +2,14 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getParserServices, + getTypeArguments, + isTypeAnyArrayType, + isTypeAnyType, + isUnsafeAssignment, +} from '../util'; type MessageIds = | 'unsafeArgument' @@ -57,13 +64,13 @@ class FunctionSignature { // is a rest param if (checker.isArrayType(type)) { restType = { - type: util.getTypeArguments(type, checker)[0], + type: getTypeArguments(type, checker)[0], kind: RestTypeKind.Array, index: i, }; } else if (checker.isTupleType(type)) { restType = { - typeArguments: util.getTypeArguments(type, checker), + typeArguments: getTypeArguments(type, checker), kind: RestTypeKind.Tuple, index: i, }; @@ -131,7 +138,7 @@ class FunctionSignature { } } -export default util.createRule<[], MessageIds>({ +export default createRule<[], MessageIds>({ name: 'no-unsafe-argument', meta: { type: 'problem', @@ -152,7 +159,7 @@ export default util.createRule<[], MessageIds>({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); return { @@ -164,7 +171,7 @@ export default util.createRule<[], MessageIds>({ } // ignore any-typed calls as these are caught by no-unsafe-call - if (util.isTypeAnyType(services.getTypeAtLocation(node.callee))) { + if (isTypeAnyType(services.getTypeAtLocation(node.callee))) { return; } @@ -182,13 +189,13 @@ export default util.createRule<[], MessageIds>({ argument.argument, ); - if (util.isTypeAnyType(spreadArgType)) { + if (isTypeAnyType(spreadArgType)) { // foo(...any) context.report({ node: argument, messageId: 'unsafeSpread', }); - } else if (util.isTypeAnyArrayType(spreadArgType, checker)) { + } else if (isTypeAnyArrayType(spreadArgType, checker)) { // foo(...any[]) // TODO - we could break down the spread and compare the array type against each argument @@ -198,7 +205,7 @@ export default util.createRule<[], MessageIds>({ }); } else if (checker.isTupleType(spreadArgType)) { // foo(...[tuple1, tuple2]) - const spreadTypeArguments = util.getTypeArguments( + const spreadTypeArguments = getTypeArguments( spreadArgType, checker, ); @@ -207,7 +214,7 @@ export default util.createRule<[], MessageIds>({ if (parameterType == null) { continue; } - const result = util.isUnsafeAssignment( + const result = isUnsafeAssignment( tupleType, parameterType, checker, @@ -246,7 +253,7 @@ export default util.createRule<[], MessageIds>({ } const argumentType = services.getTypeAtLocation(argument); - const result = util.isUnsafeAssignment( + const result = isUnsafeAssignment( argumentType, parameterType, checker, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts index 7e929071e19e..819959b781d7 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -3,8 +3,20 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import type * as ts from 'typescript'; -import * as util from '../util'; -import { getThisExpression } from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getContextualType, + getParserServices, + getThisExpression, + getTypeArguments, + isTypeAnyArrayType, + isTypeAnyType, + isTypeUnknownType, + isUnsafeAssignment, + nullThrows, + NullThrowsReasons, +} from '../util'; const enum ComparisonType { /** Do no assignment comparison */ @@ -15,7 +27,7 @@ const enum ComparisonType { Contextual, } -export default util.createRule({ +export default createRule({ name: 'no-unsafe-assignment', meta: { type: 'problem', @@ -42,7 +54,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const compilerOptions = services.program.getCompilerOptions(); const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( @@ -73,7 +85,7 @@ export default util.createRule({ ): boolean { // any array // const [x] = ([] as any[]); - if (util.isTypeAnyArrayType(senderType, checker)) { + if (isTypeAnyArrayType(senderType, checker)) { context.report({ node: receiverNode, messageId: 'unsafeArrayPattern', @@ -85,7 +97,7 @@ export default util.createRule({ return true; } - const tupleElements = util.getTypeArguments(senderType, checker); + const tupleElements = getTypeArguments(senderType, checker); // tuple with any // const [x] = [1 as any]; @@ -111,7 +123,7 @@ export default util.createRule({ } // check for the any type first so we can handle [[[x]]] = [any] - if (util.isTypeAnyType(senderType)) { + if (isTypeAnyType(senderType)) { context.report({ node: receiverElement, messageId: 'unsafeArrayPatternFromTuple', @@ -197,7 +209,7 @@ export default util.createRule({ } // check for the any type first so we can handle {x: {y: z}} = {x: any} - if (util.isTypeAnyType(senderType)) { + if (isTypeAnyType(senderType)) { context.report({ node: receiverProperty.value, messageId: 'unsafeArrayPatternFromTuple', @@ -235,14 +247,14 @@ export default util.createRule({ const receiverTsNode = services.esTreeNodeToTSNodeMap.get(receiverNode); const receiverType = comparisonType === ComparisonType.Contextual - ? util.getContextualType(checker, receiverTsNode as ts.Expression) ?? + ? getContextualType(checker, receiverTsNode as ts.Expression) ?? services.getTypeAtLocation(receiverNode) : services.getTypeAtLocation(receiverNode); const senderType = services.getTypeAtLocation(senderNode); - if (util.isTypeAnyType(senderType)) { + if (isTypeAnyType(senderType)) { // handle cases when we assign any ==> unknown. - if (util.isTypeUnknownType(receiverType)) { + if (isTypeUnknownType(receiverType)) { return false; } @@ -253,8 +265,8 @@ export default util.createRule({ const thisExpression = getThisExpression(senderNode); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation(services, thisExpression), + isTypeAnyType( + getConstrainedTypeAtLocation(services, thisExpression), ) ) { messageId = 'anyAssignmentThis'; @@ -272,7 +284,7 @@ export default util.createRule({ return false; } - const result = util.isUnsafeAssignment( + const result = isUnsafeAssignment( senderType, receiverType, checker, @@ -308,9 +320,9 @@ export default util.createRule({ 'VariableDeclarator[init != null]'( node: TSESTree.VariableDeclarator, ): void { - const init = util.nullThrows( + const init = nullThrows( node.init, - util.NullThrowsReasons.MissingToken(node.type, 'init'), + NullThrowsReasons.MissingToken(node.type, 'init'), ); let didReport = checkAssignment( node.id, @@ -368,10 +380,7 @@ export default util.createRule({ }, 'ArrayExpression > SpreadElement'(node: TSESTree.SpreadElement): void { const restType = services.getTypeAtLocation(node.argument); - if ( - util.isTypeAnyType(restType) || - util.isTypeAnyArrayType(restType, checker) - ) { + if (isTypeAnyType(restType) || isTypeAnyArrayType(restType, checker)) { context.report({ node: node, messageId: 'unsafeArraySpread', @@ -379,9 +388,9 @@ export default util.createRule({ } }, 'JSXAttribute[value != null]'(node: TSESTree.JSXAttribute): void { - const value = util.nullThrows( + const value = nullThrows( node.value, - util.NullThrowsReasons.MissingToken(node.type, 'value'), + NullThrowsReasons.MissingToken(node.type, 'value'), ); if ( value.type !== AST_NODE_TYPES.JSXExpressionContainer || diff --git a/packages/eslint-plugin/src/rules/no-unsafe-call.ts b/packages/eslint-plugin/src/rules/no-unsafe-call.ts index b47d3ee9d85d..b4ec6379f2e1 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-call.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-call.ts @@ -1,8 +1,13 @@ import type { TSESTree } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; -import * as util from '../util'; -import { getThisExpression } from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + getThisExpression, + isTypeAnyType, +} from '../util'; type MessageIds = | 'unsafeCall' @@ -10,7 +15,7 @@ type MessageIds = | 'unsafeNew' | 'unsafeTemplateTag'; -export default util.createRule<[], MessageIds>({ +export default createRule<[], MessageIds>({ name: 'no-unsafe-call', meta: { type: 'problem', @@ -32,7 +37,7 @@ export default util.createRule<[], MessageIds>({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const compilerOptions = services.program.getCompilerOptions(); const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( compilerOptions, @@ -44,16 +49,16 @@ export default util.createRule<[], MessageIds>({ reportingNode: TSESTree.Node, messageId: MessageIds, ): void { - const type = util.getConstrainedTypeAtLocation(services, node); + const type = getConstrainedTypeAtLocation(services, node); - if (util.isTypeAnyType(type)) { + if (isTypeAnyType(type)) { if (!isNoImplicitThis) { // `this()` or `this.foo()` or `this.foo[bar]()` const thisExpression = getThisExpression(node); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation(services, thisExpression), + isTypeAnyType( + getConstrainedTypeAtLocation(services, thisExpression), ) ) { messageId = 'unsafeCallThis'; diff --git a/packages/eslint-plugin/src/rules/no-unsafe-declaration-merging.ts b/packages/eslint-plugin/src/rules/no-unsafe-declaration-merging.ts index 3e034ba458a3..b7004f06a9dd 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-declaration-merging.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-declaration-merging.ts @@ -2,9 +2,9 @@ import type { Scope } from '@typescript-eslint/scope-manager'; import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'no-unsafe-declaration-merging', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts index 677eb918831f..ca08f2f7a2cd 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-enum-comparison.ts @@ -2,7 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { createRule, getParserServices } from '../util'; import { getEnumTypes } from './enum-utils/shared'; /** @@ -29,14 +29,14 @@ function typeViolates(leftTypeParts: ts.Type[], right: ts.Type): boolean { * @returns What type a type's enum value is (number or string), if either. */ function getEnumValueType(type: ts.Type): ts.TypeFlags | undefined { - return util.isTypeFlagSet(type, ts.TypeFlags.EnumLike) - ? util.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral) + return tsutils.isTypeFlagSet(type, ts.TypeFlags.EnumLike) + ? tsutils.isTypeFlagSet(type, ts.TypeFlags.NumberLiteral) ? ts.TypeFlags.Number : ts.TypeFlags.String : undefined; } -export default util.createRule({ +export default createRule({ name: 'no-unsafe-enum-comparison', meta: { type: 'suggestion', @@ -53,7 +53,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const parserServices = util.getParserServices(context); + const parserServices = getParserServices(context); const typeChecker = parserServices.program.getTypeChecker(); return { diff --git a/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts b/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts index a5a8d3c6c4b7..45aefe49e534 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts @@ -2,15 +2,20 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; -import * as util from '../util'; -import { getThisExpression } from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + getThisExpression, + isTypeAnyType, +} from '../util'; const enum State { Unsafe = 1, Safe = 2, } -export default util.createRule({ +export default createRule({ name: 'no-unsafe-member-access', meta: { type: 'problem', @@ -33,7 +38,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const compilerOptions = services.program.getCompilerOptions(); const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( compilerOptions, @@ -60,7 +65,7 @@ export default util.createRule({ } const type = services.getTypeAtLocation(node.object); - const state = util.isTypeAnyType(type) ? State.Unsafe : State.Safe; + const state = isTypeAnyType(type) ? State.Unsafe : State.Safe; stateCache.set(node, state); if (state === State.Unsafe) { @@ -75,8 +80,8 @@ export default util.createRule({ if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation(services, thisExpression), + isTypeAnyType( + getConstrainedTypeAtLocation(services, thisExpression), ) ) { messageId = 'unsafeThisMemberExpression'; @@ -116,7 +121,7 @@ export default util.createRule({ const type = services.getTypeAtLocation(node); - if (util.isTypeAnyType(type)) { + if (isTypeAnyType(type)) { const propertyName = sourceCode.getText(node); context.report({ node, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-return.ts b/packages/eslint-plugin/src/rules/no-unsafe-return.ts index 93a1226e9e4a..e5fb73a3ac92 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-return.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-return.ts @@ -3,10 +3,21 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; -import { getThisExpression } from '../util'; - -export default util.createRule({ +import { + AnyType, + createRule, + getConstrainedTypeAtLocation, + getContextualType, + getParserServices, + getThisExpression, + isAnyOrAnyArrayTypeDiscriminated, + isTypeAnyType, + isTypeUnknownArrayType, + isTypeUnknownType, + isUnsafeAssignment, +} from '../util'; + +export default createRule({ name: 'no-unsafe-return', meta: { type: 'problem', @@ -28,7 +39,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const compilerOptions = services.program.getCompilerOptions(); const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( @@ -66,17 +77,14 @@ export default util.createRule({ reportingNode: TSESTree.Node = returnNode, ): void { const tsNode = services.esTreeNodeToTSNodeMap.get(returnNode); - const anyType = util.isAnyOrAnyArrayTypeDiscriminated(tsNode, checker); + const anyType = isAnyOrAnyArrayTypeDiscriminated(tsNode, checker); const functionNode = getParentFunctionNode(returnNode); /* istanbul ignore if */ if (!functionNode) { return; } // function has an explicit return type, so ensure it's a safe return - const returnNodeType = util.getConstrainedTypeAtLocation( - services, - returnNode, - ); + const returnNodeType = getConstrainedTypeAtLocation(services, returnNode); const functionTSNode = services.esTreeNodeToTSNodeMap.get(functionNode); // function expressions will not have their return type modified based on receiver typing @@ -86,7 +94,7 @@ export default util.createRule({ let functionType = ts.isFunctionExpression(functionTSNode) || ts.isArrowFunction(functionTSNode) - ? util.getContextualType(checker, functionTSNode) + ? getContextualType(checker, functionTSNode) : services.getTypeAtLocation(functionNode); if (!functionType) { functionType = services.getTypeAtLocation(functionNode); @@ -102,20 +110,20 @@ export default util.createRule({ } } - if (anyType !== util.AnyType.Safe) { + if (anyType !== AnyType.Safe) { // Allow cases when the declared return type of the function is either unknown or unknown[] // and the function is returning any or any[]. for (const signature of functionType.getCallSignatures()) { const functionReturnType = signature.getReturnType(); if ( - anyType === util.AnyType.Any && - util.isTypeUnknownType(functionReturnType) + anyType === AnyType.Any && + isTypeUnknownType(functionReturnType) ) { return; } if ( - anyType === util.AnyType.AnyArray && - util.isTypeUnknownArrayType(functionReturnType, checker) + anyType === AnyType.AnyArray && + isTypeUnknownArrayType(functionReturnType, checker) ) { return; } @@ -128,8 +136,8 @@ export default util.createRule({ const thisExpression = getThisExpression(returnNode); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation(services, thisExpression), + isTypeAnyType( + getConstrainedTypeAtLocation(services, thisExpression), ) ) { messageId = 'unsafeReturnThis'; @@ -141,14 +149,14 @@ export default util.createRule({ node: reportingNode, messageId, data: { - type: anyType === util.AnyType.Any ? 'any' : 'any[]', + type: anyType === AnyType.Any ? 'any' : 'any[]', }, }); } for (const signature of functionType.getCallSignatures()) { const functionReturnType = signature.getReturnType(); - const result = util.isUnsafeAssignment( + const result = isUnsafeAssignment( returnNodeType, functionReturnType, checker, diff --git a/packages/eslint-plugin/src/rules/no-unused-expressions.ts b/packages/eslint-plugin/src/rules/no-unused-expressions.ts index d5eb14c93501..3c9652e46d8a 100644 --- a/packages/eslint-plugin/src/rules/no-unused-expressions.ts +++ b/packages/eslint-plugin/src/rules/no-unused-expressions.ts @@ -1,15 +1,19 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-unused-expressions'); -type MessageIds = util.InferMessageIdsTypeFromRule; -type Options = util.InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'no-unused-expressions', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/no-unused-vars.ts b/packages/eslint-plugin/src/rules/no-unused-vars.ts index 7c174482dcdc..eec4e9d6ef4f 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars.ts @@ -2,7 +2,15 @@ import { PatternVisitor } from '@typescript-eslint/scope-manager'; import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + collectUnusedVariables as _collectUnusedVariables, + createRule, + getNameLocationInGlobalDirectiveComment, + isDefinitionFile, + isFunction, + nullThrows, + NullThrowsReasons, +} from '../util'; export type MessageIds = 'unusedVar'; export type Options = [ @@ -31,7 +39,7 @@ interface TranslatedOptions { destructuredArrayIgnorePattern?: RegExp; } -export default util.createRule({ +export default createRule({ name: 'no-unused-vars', meta: { type: 'problem', @@ -197,7 +205,7 @@ export default util.createRule({ ); } - const unusedVariablesOriginal = util.collectUnusedVariables(context); + const unusedVariablesOriginal = _collectUnusedVariables(context); const unusedVariablesReturn: TSESLint.Scope.Variable[] = []; for (const variable of unusedVariablesOriginal) { // explicit global variables don't have definitions. @@ -258,7 +266,7 @@ export default util.createRule({ // if "args" option is "after-used", skip used variables if ( options.args === 'after-used' && - util.isFunction(def.name.parent) && + isFunction(def.name.parent) && !isAfterLastUsedArg(variable) ) { continue; @@ -294,7 +302,7 @@ export default util.createRule({ [ambientDeclarationSelector(AST_NODE_TYPES.Program, true)]( node: DeclarationSelectorNode, ): void { - if (!util.isDefinitionFile(filename)) { + if (!isDefinitionFile(filename)) { return; } markDeclarationChildAsUsed(node); @@ -330,9 +338,9 @@ export default util.createRule({ 'TSModuleDeclaration[declare = true] > TSModuleBlock', false, )](node: DeclarationSelectorNode): void { - const moduleDecl = util.nullThrows( + const moduleDecl = nullThrows( node.parent?.parent, - util.NullThrowsReasons.MissingParent, + NullThrowsReasons.MissingParent, ) as TSESTree.TSModuleDeclaration; // declared ambient modules with an `export =` statement will only export that one thing @@ -451,7 +459,7 @@ export default util.createRule({ context.report({ node: programNode, - loc: util.getNameLocationInGlobalDirectiveComment( + loc: getNameLocationInGlobalDirectiveComment( sourceCode, directiveComment, unusedVar.name, diff --git a/packages/eslint-plugin/src/rules/no-use-before-define.ts b/packages/eslint-plugin/src/rules/no-use-before-define.ts index 7d15cd25a19d..67f6ee524b86 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -2,7 +2,7 @@ import { DefinitionType } from '@typescript-eslint/scope-manager'; import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, TSESLint } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; @@ -236,7 +236,7 @@ interface Config { type Options = [Config | 'nofunc']; type MessageIds = 'noUseBeforeDefine'; -export default util.createRule({ +export default createRule({ name: 'no-use-before-define', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-useless-constructor.ts b/packages/eslint-plugin/src/rules/no-useless-constructor.ts index 6409b8a48c34..8066674e5408 100644 --- a/packages/eslint-plugin/src/rules/no-useless-constructor.ts +++ b/packages/eslint-plugin/src/rules/no-useless-constructor.ts @@ -1,13 +1,17 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('no-useless-constructor'); -type Options = util.InferOptionsTypeFromRule; -type MessageIds = util.InferMessageIdsTypeFromRule; +type Options = InferOptionsTypeFromRule; +type MessageIds = InferMessageIdsTypeFromRule; /** * Check if method with accessibility is not useless @@ -41,7 +45,7 @@ function checkParams(node: TSESTree.MethodDefinition): boolean { ); } -export default util.createRule({ +export default createRule({ name: 'no-useless-constructor', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/no-useless-empty-export.ts b/packages/eslint-plugin/src/rules/no-useless-empty-export.ts index 7c2b8ca3ea22..5d6b091e2abb 100644 --- a/packages/eslint-plugin/src/rules/no-useless-empty-export.ts +++ b/packages/eslint-plugin/src/rules/no-useless-empty-export.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; function isEmptyExport( node: TSESTree.Node, @@ -23,7 +23,7 @@ const exportOrImportNodeTypes = new Set([ AST_NODE_TYPES.TSImportEqualsDeclaration, ]); -export default util.createRule({ +export default createRule({ name: 'no-useless-empty-export', meta: { docs: { diff --git a/packages/eslint-plugin/src/rules/no-var-requires.ts b/packages/eslint-plugin/src/rules/no-var-requires.ts index b8655d049d30..61a300678215 100644 --- a/packages/eslint-plugin/src/rules/no-var-requires.ts +++ b/packages/eslint-plugin/src/rules/no-var-requires.ts @@ -1,12 +1,12 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, ASTUtils } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Options = []; type MessageIds = 'noVarReqs'; -export default util.createRule({ +export default createRule({ name: 'no-var-requires', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts index 4523715d1fbd..c9dcdf8fee9a 100644 --- a/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts +++ b/packages/eslint-plugin/src/rules/non-nullable-type-assertion-style.ts @@ -3,9 +3,14 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; - -export default util.createRule({ +import { + createRule, + getOperatorPrecedence, + getParserServices, + OperatorPrecedence, +} from '../util'; + +export default createRule({ name: 'non-nullable-type-assertion-style', meta: { docs: { @@ -24,7 +29,7 @@ export default util.createRule({ defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const sourceCode = context.getSourceCode(); const getTypesIfNotLoose = (node: TSESTree.Node): ts.Type[] | undefined => { @@ -117,10 +122,10 @@ export default util.createRule({ const expressionSourceCode = sourceCode.getText(node.expression); const higherPrecedenceThanUnary = - util.getOperatorPrecedence( + getOperatorPrecedence( services.esTreeNodeToTSNodeMap.get(node.expression).kind, ts.SyntaxKind.Unknown, - ) > util.OperatorPrecedence.Unary; + ) > OperatorPrecedence.Unary; context.report({ fix(fixer) { 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 d2342adc8699..255ceb0c712a 100644 --- a/packages/eslint-plugin/src/rules/padding-line-between-statements.ts +++ b/packages/eslint-plugin/src/rules/padding-line-between-statements.ts @@ -1,7 +1,15 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + isClosingBraceToken, + isFunction, + isNotSemicolonToken, + isParenthesized, + isSemicolonToken, + isTokenOnSameLine, +} from '../util'; /** * This rule is a replica of padding-line-between-statements. @@ -141,7 +149,7 @@ function isIIFEStatement(node: TSESTree.Node): boolean { while (node.type === AST_NODE_TYPES.SequenceExpression) { node = node.expressions[node.expressions.length - 1]; } - return util.isFunction(node); + return isFunction(node); } } return false; @@ -201,9 +209,9 @@ function isBlockLikeStatement( } // Checks the last token is a closing brace of blocks. - const lastToken = sourceCode.getLastToken(node, util.isNotSemicolonToken); + const lastToken = sourceCode.getLastToken(node, isNotSemicolonToken); const belongingNode = - lastToken && util.isClosingBraceToken(lastToken) + lastToken && isClosingBraceToken(lastToken) ? sourceCode.getNodeByRangeIndex(lastToken.range[0]) : null; @@ -228,10 +236,10 @@ function isDirective( node.type === AST_NODE_TYPES.ExpressionStatement && (node.parent?.type === AST_NODE_TYPES.Program || (node.parent?.type === AST_NODE_TYPES.BlockStatement && - util.isFunction(node.parent.parent))) && + isFunction(node.parent.parent))) && node.expression.type === AST_NODE_TYPES.Literal && typeof node.expression.value === 'string' && - !util.isParenthesized(node.expression, sourceCode) + !isParenthesized(node.expression, sourceCode) ); } @@ -332,7 +340,7 @@ function getActualLastToken( prevToken && nextToken && prevToken.range[0] >= node.range[0] && - util.isSemicolonToken(semiToken) && + isSemicolonToken(semiToken) && semiToken.loc.start.line !== prevToken.loc.end.line && semiToken.loc.end.line === nextToken.loc.start.line; @@ -464,14 +472,14 @@ function verifyForAlways( * @private */ filter(token) { - if (util.isTokenOnSameLine(prevToken, token)) { + if (isTokenOnSameLine(prevToken, token)) { prevToken = token; return false; } return true; }, })! || nextNode; - const insertText = util.isTokenOnSameLine(prevToken, nextToken) + const insertText = isTokenOnSameLine(prevToken, nextToken) ? '\n\n' : '\n'; @@ -581,7 +589,7 @@ const StatementTypes: Record = { // Rule Definition //------------------------------------------------------------------------------ -export default util.createRule({ +export default createRule({ name: 'padding-line-between-statements', meta: { type: 'layout', diff --git a/packages/eslint-plugin/src/rules/parameter-properties.ts b/packages/eslint-plugin/src/rules/parameter-properties.ts index 8ee987caaf3b..1d7d5d7ccadb 100644 --- a/packages/eslint-plugin/src/rules/parameter-properties.ts +++ b/packages/eslint-plugin/src/rules/parameter-properties.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Modifier = | 'private readonly' @@ -23,7 +23,7 @@ type Options = [ type MessageIds = 'preferClassProperty' | 'preferParameterProperty'; -export default util.createRule({ +export default createRule({ name: 'parameter-properties', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/prefer-as-const.ts b/packages/eslint-plugin/src/rules/prefer-as-const.ts index 5372e0ed3b0e..f13430b59fed 100644 --- a/packages/eslint-plugin/src/rules/prefer-as-const.ts +++ b/packages/eslint-plugin/src/rules/prefer-as-const.ts @@ -1,9 +1,9 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'prefer-as-const', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/prefer-enum-initializers.ts b/packages/eslint-plugin/src/rules/prefer-enum-initializers.ts index 50ce4a7de6b9..a1df9525e801 100644 --- a/packages/eslint-plugin/src/rules/prefer-enum-initializers.ts +++ b/packages/eslint-plugin/src/rules/prefer-enum-initializers.ts @@ -1,10 +1,10 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type MessageIds = 'defineInitializer' | 'defineInitializerSuggestion'; -export default util.createRule<[], MessageIds>({ +export default createRule<[], MessageIds>({ name: 'prefer-enum-initializers', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/prefer-for-of.ts b/packages/eslint-plugin/src/rules/prefer-for-of.ts index d326b1114fd8..a7ee36868bd9 100644 --- a/packages/eslint-plugin/src/rules/prefer-for-of.ts +++ b/packages/eslint-plugin/src/rules/prefer-for-of.ts @@ -1,9 +1,9 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'prefer-for-of', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/prefer-function-type.ts b/packages/eslint-plugin/src/rules/prefer-function-type.ts index a861104ce869..9655093236eb 100644 --- a/packages/eslint-plugin/src/rules/prefer-function-type.ts +++ b/packages/eslint-plugin/src/rules/prefer-function-type.ts @@ -1,14 +1,14 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; export const phrases = { [AST_NODE_TYPES.TSTypeLiteral]: 'Type literal', [AST_NODE_TYPES.TSInterfaceDeclaration]: 'Interface', } as const; -export default util.createRule({ +export default createRule({ name: 'prefer-function-type', meta: { docs: { diff --git a/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts b/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts index 1aa0919d04b3..0c945a6b29d5 100644 --- a/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts +++ b/packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts @@ -1,8 +1,8 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; -export default util.createRule({ +export default createRule({ name: 'prefer-namespace-keyword', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index d4f790770a51..e9e340f93240 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -3,7 +3,18 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getParserServices, + getTypeFlags, + isLogicalOrOperator, + isNodeEqual, + isNullableType, + isNullLiteral, + isUndefinedIdentifier, + nullThrows, + NullThrowsReasons, +} from '../util'; export type Options = [ { @@ -28,7 +39,7 @@ export type MessageIds = | 'preferNullishOverTernary' | 'suggestNullish'; -export default util.createRule({ +export default createRule({ name: 'prefer-nullish-coalescing', meta: { type: 'suggestion', @@ -112,7 +123,7 @@ export default util.createRule({ }, ], ) { - const parserServices = util.getParserServices(context); + const parserServices = getParserServices(context); const compilerOptions = parserServices.program.getCompilerOptions(); const sourceCode = context.getSourceCode(); const checker = parserServices.program.getTypeChecker(); @@ -208,18 +219,18 @@ export default util.createRule({ // we check that the test only contains null, undefined and the identifier for (const testNode of nodesInsideTestExpression) { - if (util.isNullLiteral(testNode)) { + if (isNullLiteral(testNode)) { hasNullCheck = true; - } else if (util.isUndefinedIdentifier(testNode)) { + } else if (isUndefinedIdentifier(testNode)) { hasUndefinedCheck = true; } else if ( (operator === '!==' || operator === '!=') && - util.isNodeEqual(testNode, node.consequent) + isNodeEqual(testNode, node.consequent) ) { identifier = testNode; } else if ( (operator === '===' || operator === '==') && - util.isNodeEqual(testNode, node.alternate) + isNodeEqual(testNode, node.alternate) ) { identifier = testNode; } else { @@ -244,7 +255,7 @@ export default util.createRule({ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(identifier); const type = checker.getTypeAtLocation(tsNode); - const flags = util.getTypeFlags(type); + const flags = getTypeFlags(type); if (flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { return false; @@ -297,7 +308,7 @@ export default util.createRule({ ): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(tsNode.left); - const isNullish = util.isNullableType(type, { allowUndefined: true }); + const isNullish = isNullableType(type, { allowUndefined: true }); if (!isNullish) { return; } @@ -333,24 +344,24 @@ export default util.createRule({ return; } - const barBarOperator = util.nullThrows( + const barBarOperator = nullThrows( sourceCode.getTokenAfter( node.left, token => token.type === AST_TOKEN_TYPES.Punctuator && token.value === node.operator, ), - util.NullThrowsReasons.MissingToken('operator', node.type), + NullThrowsReasons.MissingToken('operator', node.type), ); function* fix( fixer: TSESLint.RuleFixer, ): IterableIterator { - if (node.parent && util.isLogicalOrOperator(node.parent)) { + if (node.parent && isLogicalOrOperator(node.parent)) { // '&&' and '??' operations cannot be mixed without parentheses (e.g. a && b ?? c) if ( node.left.type === AST_NODE_TYPES.LogicalExpression && - !util.isLogicalOrOperator(node.left.left) + !isLogicalOrOperator(node.left.left) ) { yield fixer.insertTextBefore(node.left.right, '('); } else { diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts index 27c8941af7ea..5e0508925a47 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts @@ -9,10 +9,16 @@ import type { RuleContext, SourceCode, } from '@typescript-eslint/utils/ts-eslint'; -import { unionTypeParts } from 'ts-api-utils'; +import { isTypeFlagSet, unionTypeParts } from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../../util'; +import { + getOperatorPrecedenceForNode, + isOpeningParenToken, + nullThrows, + NullThrowsReasons, + OperatorPrecedence, +} from '../../util'; import { compareNodes, NodeComparisonResult } from './compareNodes'; import type { ValidOperand } from './gatherLogicalOperands'; import { NullishComparisonType } from './gatherLogicalOperands'; @@ -29,7 +35,7 @@ function includesType( const typeFlag = typeFlagIn | ts.TypeFlags.Any | ts.TypeFlags.Unknown; const types = unionTypeParts(parserServices.getTypeAtLocation(node)); for (const type of types) { - if (util.isTypeFlagSet(type, typeFlag)) { + if (isTypeFlagSet(type, typeFlag)) { return true; } } @@ -306,8 +312,8 @@ function getFixer( } } if ( - part.precedence !== util.OperatorPrecedence.Invalid && - part.precedence < util.OperatorPrecedence.Member + part.precedence !== OperatorPrecedence.Invalid && + part.precedence < OperatorPrecedence.Member ) { str += `(${part.text})`; } else { @@ -362,7 +368,7 @@ function getFixer( interface FlattenedChain { nonNull: boolean; optional: boolean; - precedence: util.OperatorPrecedence; + precedence: OperatorPrecedence; requiresDot: boolean; text: string; } @@ -376,23 +382,17 @@ function getFixer( case AST_NODE_TYPES.CallExpression: { const argumentsText = (() => { - const closingParenToken = util.nullThrows( + const closingParenToken = nullThrows( sourceCode.getLastToken(node), - util.NullThrowsReasons.MissingToken( - 'closing parenthesis', - node.type, - ), + NullThrowsReasons.MissingToken('closing parenthesis', node.type), ); - const openingParenToken = util.nullThrows( + const openingParenToken = nullThrows( sourceCode.getFirstTokenBetween( node.typeArguments ?? node.callee, closingParenToken, - util.isOpeningParenToken, - ), - util.NullThrowsReasons.MissingToken( - 'opening parenthesis', - node.type, + isOpeningParenToken, ), + NullThrowsReasons.MissingToken('opening parenthesis', node.type), ); return sourceCode.text.substring( openingParenToken.range[0], @@ -414,7 +414,7 @@ function getFixer( nonNull: false, optional: node.optional, // no precedence for this - precedence: util.OperatorPrecedence.Invalid, + precedence: OperatorPrecedence.Invalid, requiresDot: false, text: typeArgumentsText + argumentsText, }, @@ -430,8 +430,8 @@ function getFixer( optional: node.optional, precedence: node.computed ? // computed is already wrapped in [] so no need to wrap in () as well - util.OperatorPrecedence.Invalid - : util.getOperatorPrecedenceForNode(node.property), + OperatorPrecedence.Invalid + : getOperatorPrecedenceForNode(node.property), requiresDot: !node.computed, text: node.computed ? `[${propertyText}]` : propertyText, }, @@ -446,7 +446,7 @@ function getFixer( { nonNull: false, optional: false, - precedence: util.getOperatorPrecedenceForNode(node), + precedence: getOperatorPrecedenceForNode(node), requiresDot: false, text: sourceCode.getText(node), }, diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts index 4b033fded576..a9fd4055a927 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts @@ -8,11 +8,12 @@ import { isBooleanLiteralType, isNumberLiteralType, isStringLiteralType, + isTypeFlagSet, unionTypeParts, } from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../../util'; +import {} from '../../util'; import type { PreferOptionalChainOptions } from './PreferOptionalChainOptions'; const enum ComparisonValueType { @@ -94,7 +95,7 @@ function isValidFalseBooleanCheckType( } if (options.requireNullish === true) { - return types.some(t => util.isTypeFlagSet(t, NULLISH_FLAGS)); + return types.some(t => isTypeFlagSet(t, NULLISH_FLAGS)); } let allowedFlags = NULLISH_FLAGS | ts.TypeFlags.Object; @@ -116,7 +117,7 @@ function isValidFalseBooleanCheckType( if (options.checkBigInt === true) { allowedFlags |= ts.TypeFlags.BigIntLike; } - return types.every(t => util.isTypeFlagSet(t, allowedFlags)); + return types.every(t => isTypeFlagSet(t, allowedFlags)); } export function gatherLogicalOperands( diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index f88e37cb7371..a1e9bb95f22d 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -3,7 +3,12 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import type { RuleFix } from '@typescript-eslint/utils/ts-eslint'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getOperatorPrecedence, + getParserServices, + OperatorPrecedence, +} from '../util'; import { analyzeChain } from './prefer-optional-chain-utils/analyzeChain'; import type { ValidOperand } from './prefer-optional-chain-utils/gatherLogicalOperands'; import { @@ -15,7 +20,7 @@ import type { PreferOptionalChainOptions, } from './prefer-optional-chain-utils/PreferOptionalChainOptions'; -export default util.createRule< +export default createRule< [PreferOptionalChainOptions], PreferOptionalChainMessageIds >({ @@ -98,7 +103,7 @@ export default util.createRule< ], create(context, [options]) { const sourceCode = context.getSourceCode(); - const parserServices = util.getParserServices(context); + const parserServices = getParserServices(context); const seenLogicals = new Set(); @@ -131,12 +136,12 @@ export default util.createRule< const operator = ts.isBinaryExpression(logicalTsNode) ? logicalTsNode.operatorToken.kind : ts.SyntaxKind.Unknown; - const leftPrecedence = util.getOperatorPrecedence( + const leftPrecedence = getOperatorPrecedence( leftTsNode.kind, operator, ); - return leftPrecedence < util.OperatorPrecedence.LeftHandSide; + return leftPrecedence < OperatorPrecedence.LeftHandSide; } context.report({ node: parentNode, 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 e22ab9885e4a..72b73a883520 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly-parameter-types.ts @@ -1,11 +1,18 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { TypeOrValueSpecifier } from '../util'; +import { + createRule, + getParserServices, + isTypeReadonly, + readonlynessOptionsDefaults, + readonlynessOptionsSchema, +} from '../util'; type Options = [ { - allow?: util.TypeOrValueSpecifier[]; + allow?: TypeOrValueSpecifier[]; checkParameterProperties?: boolean; ignoreInferredTypes?: boolean; treatMethodsAsReadonly?: boolean; @@ -13,7 +20,7 @@ type Options = [ ]; type MessageIds = 'shouldBeReadonly'; -export default util.createRule({ +export default createRule({ name: 'prefer-readonly-parameter-types', meta: { type: 'suggestion', @@ -27,7 +34,7 @@ export default util.createRule({ type: 'object', additionalProperties: false, properties: { - allow: util.readonlynessOptionsSchema.properties.allow, + allow: readonlynessOptionsSchema.properties.allow, checkParameterProperties: { type: 'boolean', }, @@ -35,7 +42,7 @@ export default util.createRule({ type: 'boolean', }, treatMethodsAsReadonly: - util.readonlynessOptionsSchema.properties.treatMethodsAsReadonly, + readonlynessOptionsSchema.properties.treatMethodsAsReadonly, }, }, ], @@ -45,11 +52,11 @@ export default util.createRule({ }, defaultOptions: [ { - allow: util.readonlynessOptionsDefaults.allow, + allow: readonlynessOptionsDefaults.allow, checkParameterProperties: true, ignoreInferredTypes: false, treatMethodsAsReadonly: - util.readonlynessOptionsDefaults.treatMethodsAsReadonly, + readonlynessOptionsDefaults.treatMethodsAsReadonly, }, ], create( @@ -63,7 +70,7 @@ export default util.createRule({ }, ], ) { - const services = util.getParserServices(context); + const services = getParserServices(context); return { [[ @@ -106,7 +113,7 @@ export default util.createRule({ } const type = services.getTypeAtLocation(actualParam); - const isReadOnly = util.isTypeReadonly(services.program, type, { + const isReadOnly = isTypeReadonly(services.program, type, { treatMethodsAsReadonly: treatMethodsAsReadonly!, allow, }); diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 713a703a56f0..f5fe608bb15b 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -3,8 +3,7 @@ import { AST_NODE_TYPES, ASTUtils } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; -import { typeIsOrHasBaseType } from '../util'; +import { createRule, getParserServices, typeIsOrHasBaseType } from '../util'; type MessageIds = 'preferReadonly'; type Options = [ @@ -20,7 +19,7 @@ const functionScopeBoundaries = [ AST_NODE_TYPES.MethodDefinition, ].join(', '); -export default util.createRule({ +export default createRule({ name: 'prefer-readonly', meta: { docs: { @@ -48,7 +47,7 @@ export default util.createRule({ }, defaultOptions: [{ onlyInlineLambdas: false }], create(context, [{ onlyInlineLambdas }]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const classScopeStack: ClassScope[] = []; diff --git a/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts b/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts index 8c966eeea97d..e1f3ce4783c1 100644 --- a/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts +++ b/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts @@ -1,7 +1,12 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + isTypeAssertion, +} from '../util'; type MemberExpressionWithCallExpressionParent = TSESTree.MemberExpression & { parent: TSESTree.CallExpression; @@ -24,7 +29,7 @@ const getMemberExpressionName = ( return null; }; -export default util.createRule({ +export default createRule({ name: 'prefer-reduce-type-parameter', meta: { type: 'problem', @@ -43,7 +48,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); return { @@ -56,15 +61,12 @@ export default util.createRule({ const [, secondArg] = callee.parent.arguments; - if ( - callee.parent.arguments.length < 2 || - !util.isTypeAssertion(secondArg) - ) { + if (callee.parent.arguments.length < 2 || !isTypeAssertion(secondArg)) { return; } // Get the symbol of the `reduce` method. - const calleeObjType = util.getConstrainedTypeAtLocation( + const calleeObjType = getConstrainedTypeAtLocation( services, callee.object, ); diff --git a/packages/eslint-plugin/src/rules/prefer-ts-expect-error.ts b/packages/eslint-plugin/src/rules/prefer-ts-expect-error.ts index 8ef1c7ad9273..d388be9ec955 100644 --- a/packages/eslint-plugin/src/rules/prefer-ts-expect-error.ts +++ b/packages/eslint-plugin/src/rules/prefer-ts-expect-error.ts @@ -2,11 +2,11 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import type { RuleFix, RuleFixer } from '@typescript-eslint/utils/ts-eslint'; -import * as util from '../util'; +import { createRule } from '../util'; type MessageIds = 'preferExpectErrorComment'; -export default util.createRule<[], MessageIds>({ +export default createRule<[], MessageIds>({ name: 'prefer-ts-expect-error', meta: { type: 'problem', diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index ba671d5929b0..334f8d008f4b 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -2,7 +2,13 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + containsAllTypesByName, + createRule, + getFunctionHeadLoc, + getParserServices, + isTypeFlagSet, +} from '../util'; type Options = [ { @@ -16,7 +22,7 @@ type Options = [ ]; type MessageIds = 'missingAsync'; -export default util.createRule({ +export default createRule({ name: 'promise-function-async', meta: { type: 'suggestion', @@ -90,7 +96,7 @@ export default util.createRule({ 'Promise', ...allowedPromiseNames!, ]); - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const sourceCode = context.getSourceCode(); @@ -107,7 +113,7 @@ export default util.createRule({ const returnType = checker.getReturnTypeOfSignature(signatures[0]); if ( - !util.containsAllTypesByName( + !containsAllTypesByName( returnType, allowAny!, allAllowedPromiseNames, @@ -133,21 +139,19 @@ export default util.createRule({ return; } - if ( - util.isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown) - ) { + if (isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { // Report without auto fixer because the return type is unknown return context.report({ messageId: 'missingAsync', node, - loc: util.getFunctionHeadLoc(node, sourceCode), + loc: getFunctionHeadLoc(node, sourceCode), }); } context.report({ messageId: 'missingAsync', node, - loc: util.getFunctionHeadLoc(node, sourceCode), + loc: getFunctionHeadLoc(node, sourceCode), fix: fixer => { if ( node.parent.type === AST_NODE_TYPES.MethodDefinition || diff --git a/packages/eslint-plugin/src/rules/quotes.ts b/packages/eslint-plugin/src/rules/quotes.ts index b5f2f7f57b03..74c41d6130d0 100644 --- a/packages/eslint-plugin/src/rules/quotes.ts +++ b/packages/eslint-plugin/src/rules/quotes.ts @@ -1,15 +1,19 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('quotes'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'quotes', meta: { type: 'layout', diff --git a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts index a3617894ee79..4097362bb247 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -1,6 +1,13 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + getTypeArguments, + getTypeName, + isTypeArrayTypeOrUnionOfArrayTypes, +} from '../util'; export type Options = [ { @@ -9,7 +16,7 @@ export type Options = [ ]; export type MessageIds = 'requireCompare'; -export default util.createRule({ +export default createRule({ name: 'require-array-sort-compare', defaultOptions: [ { @@ -43,7 +50,7 @@ export default util.createRule({ }, create(context, [options]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); /** @@ -54,10 +61,8 @@ export default util.createRule({ const type = services.getTypeAtLocation(node); if (checker.isArrayType(type) || checker.isTupleType(type)) { - const typeArgs = util.getTypeArguments(type, checker); - return typeArgs.every( - arg => util.getTypeName(checker, arg) === 'string', - ); + const typeArgs = getTypeArguments(type, checker); + return typeArgs.every(arg => getTypeName(checker, arg) === 'string'); } return false; } @@ -66,7 +71,7 @@ export default util.createRule({ "CallExpression[arguments.length=0] > MemberExpression[property.name='sort'][computed=false]"( callee: TSESTree.MemberExpression, ): void { - const calleeObjType = util.getConstrainedTypeAtLocation( + const calleeObjType = getConstrainedTypeAtLocation( services, callee.object, ); @@ -75,7 +80,7 @@ export default util.createRule({ return; } - if (util.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) { + if (isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) { context.report({ node: callee.parent, messageId: 'requireCompare' }); } }, diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index de3624ecbf7d..86049b04e587 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -3,7 +3,16 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import type * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getFunctionNameWithKind, + getParserServices, + isArrowToken, + isOpeningParenToken, + nullThrows, + NullThrowsReasons, + upperCaseFirst, +} from '../util'; interface ScopeInfo { upper: ScopeInfo | null; @@ -17,7 +26,7 @@ type FunctionNode = | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression; -export default util.createRule({ +export default createRule({ name: 'require-await', meta: { type: 'suggestion', @@ -34,7 +43,7 @@ export default util.createRule({ }, defaultOptions: [], create(context) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const sourceCode = context.getSourceCode(); @@ -74,7 +83,7 @@ export default util.createRule({ loc: getFunctionHeadLoc(node, sourceCode), messageId: 'missingAwait', data: { - name: util.upperCaseFirst(util.getFunctionNameWithKind(node)), + name: upperCaseFirst(getFunctionNameWithKind(node)), }, }); } @@ -186,11 +195,11 @@ function getOpeningParenOfParams( node: FunctionNode, sourceCode: TSESLint.SourceCode, ): TSESTree.Token { - return util.nullThrows( + return nullThrows( node.id - ? sourceCode.getTokenAfter(node.id, util.isOpeningParenToken) - : sourceCode.getFirstToken(node, util.isOpeningParenToken), - util.NullThrowsReasons.MissingToken('(', node.type), + ? sourceCode.getTokenAfter(node.id, isOpeningParenToken) + : sourceCode.getFirstToken(node, isOpeningParenToken), + NullThrowsReasons.MissingToken('(', node.type), ); } @@ -202,17 +211,14 @@ function getFunctionHeadLoc( node: FunctionNode, sourceCode: TSESLint.SourceCode, ): TSESTree.SourceLocation { - const parent = util.nullThrows( - node.parent, - util.NullThrowsReasons.MissingParent, - ); + const parent = nullThrows(node.parent, NullThrowsReasons.MissingParent); let start = null; let end = null; if (node.type === AST_NODE_TYPES.ArrowFunctionExpression) { - const arrowToken = util.nullThrows( - sourceCode.getTokenBefore(node.body, util.isArrowToken), - util.NullThrowsReasons.MissingToken('=>', node.type), + const arrowToken = nullThrows( + sourceCode.getTokenBefore(node.body, isArrowToken), + NullThrowsReasons.MissingToken('=>', node.type), ); start = arrowToken.loc.start; diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index 6d2cc2222eaa..99c331bbae4e 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -2,7 +2,13 @@ import type { TSESTree } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + getTypeName, + isTypeAnyType, +} from '../util'; type Options = [ { @@ -17,7 +23,7 @@ type Options = [ type MessageIds = 'bigintAndNumber' | 'invalid' | 'mismatched'; -export default util.createRule({ +export default createRule({ name: 'restrict-plus-operands', meta: { type: 'problem', @@ -93,7 +99,7 @@ export default util.createRule({ }, ], ) { - const services = util.getParserServices(context); + const services = getParserServices(context); const typeChecker = services.program.getTypeChecker(); const stringLikes = [ @@ -111,7 +117,7 @@ export default util.createRule({ function getTypeConstrained(node: TSESTree.Node): ts.Type { return typeChecker.getBaseTypeOfLiteralType( - util.getConstrainedTypeAtLocation(services, node), + getConstrainedTypeAtLocation(services, node), ); } @@ -150,7 +156,7 @@ export default util.createRule({ (!allowBoolean && isTypeFlagSetInUnion(baseType, ts.TypeFlags.BooleanLike)) || (!allowNullish && - util.isTypeFlagSet( + tsutils.isTypeFlagSet( baseType, ts.TypeFlags.Null | ts.TypeFlags.Undefined, )) @@ -169,12 +175,12 @@ export default util.createRule({ // RegExps also contain ts.TypeFlags.Any & ts.TypeFlags.Object for (const subBaseType of tsutils.unionTypeParts(baseType)) { - const typeName = util.getTypeName(typeChecker, subBaseType); + const typeName = getTypeName(typeChecker, subBaseType); if ( typeName === 'RegExp' ? !allowRegExp || tsutils.isTypeFlagSet(otherType, ts.TypeFlags.NumberLike) - : (!allowAny && util.isTypeAnyType(subBaseType)) || + : (!allowAny && isTypeAnyType(subBaseType)) || isDeeplyObjectType(subBaseType) ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index 5da963a8219e..63a0b171306a 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -2,7 +2,15 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + getTypeName, + isTypeAnyType, + isTypeFlagSet, + isTypeNeverType, +} from '../util'; type Options = [ { @@ -17,7 +25,7 @@ type Options = [ type MessageId = 'invalidType'; -export default util.createRule({ +export default createRule({ name: 'restrict-template-expressions', meta: { type: 'problem', @@ -79,47 +87,44 @@ export default util.createRule({ }, ], create(context, [options]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); function isUnderlyingTypePrimitive(type: ts.Type): boolean { - if (util.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { + if (isTypeFlagSet(type, ts.TypeFlags.StringLike)) { return true; } if ( options.allowNumber && - util.isTypeFlagSet( - type, - ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, - ) + isTypeFlagSet(type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike) ) { return true; } if ( options.allowBoolean && - util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) + isTypeFlagSet(type, ts.TypeFlags.BooleanLike) ) { return true; } - if (options.allowAny && util.isTypeAnyType(type)) { + if (options.allowAny && isTypeAnyType(type)) { return true; } - if (options.allowRegExp && util.getTypeName(checker, type) === 'RegExp') { + if (options.allowRegExp && getTypeName(checker, type) === 'RegExp') { return true; } if ( options.allowNullish && - util.isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined) + isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined) ) { return true; } - if (options.allowNever && util.isTypeNeverType(type)) { + if (options.allowNever && isTypeNeverType(type)) { return true; } @@ -134,7 +139,7 @@ export default util.createRule({ } for (const expression of node.expressions) { - const expressionType = util.getConstrainedTypeAtLocation( + const expressionType = getConstrainedTypeAtLocation( services, expression, ); diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index ed40fb967d95..df0810d41c05 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -3,7 +3,14 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getParserServices, + isAwaitExpression, + isAwaitKeyword, + isTypeAnyType, + isTypeUnknownType, +} from '../util'; import { getOperatorPrecedence } from '../util/getOperatorPrecedence'; type FunctionNode = @@ -16,7 +23,7 @@ interface ScopeInfo { owningFunc: FunctionNode; } -export default util.createRule({ +export default createRule({ name: 'return-await', meta: { docs: { @@ -45,7 +52,7 @@ export default util.createRule({ defaultOptions: ['in-try-catch'], create(context, [option]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const sourceCode = context.getSourceCode(); @@ -126,11 +133,11 @@ export default util.createRule({ node: TSESTree.Expression, ): TSESLint.RuleFix | null { // Should always be an await node; but let's be safe. - /* istanbul ignore if */ if (!util.isAwaitExpression(node)) { + /* istanbul ignore if */ if (!isAwaitExpression(node)) { return null; } - const awaitToken = sourceCode.getFirstToken(node, util.isAwaitKeyword); + const awaitToken = sourceCode.getFirstToken(node, isAwaitKeyword); // Should always be the case; but let's be safe. /* istanbul ignore if */ if (!awaitToken) { return null; @@ -195,9 +202,7 @@ export default util.createRule({ if (isAwait && !isThenable) { // any/unknown could be thenable; do not auto-fix - const useAutoFix = !( - util.isTypeAnyType(type) || util.isTypeUnknownType(type) - ); + const useAutoFix = !(isTypeAnyType(type) || isTypeUnknownType(type)); const fix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix | null => removeAwait(fixer, node); diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 1719bc247007..2129c27f9fb7 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -1,15 +1,19 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('semi'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'semi', meta: { type: 'layout', diff --git a/packages/eslint-plugin/src/rules/sort-type-constituents.ts b/packages/eslint-plugin/src/rules/sort-type-constituents.ts index fd975d42073c..552599312e19 100644 --- a/packages/eslint-plugin/src/rules/sort-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/sort-type-constituents.ts @@ -1,8 +1,7 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; -import { getEnumNames, typeNodeRequiresParentheses } from '../util'; +import { createRule, getEnumNames, typeNodeRequiresParentheses } from '../util'; enum Group { conditional = 'conditional', @@ -105,7 +104,7 @@ export type Options = [ ]; export type MessageIds = 'notSorted' | 'notSortedNamed' | 'suggestFix'; -export default util.createRule({ +export default createRule({ name: 'sort-type-constituents', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/space-before-blocks.ts b/packages/eslint-plugin/src/rules/space-before-blocks.ts index 4f82bb785a13..902c47e5ce2e 100644 --- a/packages/eslint-plugin/src/rules/space-before-blocks.ts +++ b/packages/eslint-plugin/src/rules/space-before-blocks.ts @@ -1,14 +1,18 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, isTokenOnSameLine } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('space-before-blocks'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; -export default util.createRule({ +export default createRule({ name: 'space-before-blocks', meta: { type: 'layout', @@ -44,7 +48,7 @@ export default util.createRule({ node: TSESTree.Token | TSESTree.TSInterfaceBody, ): void { const precedingToken = sourceCode.getTokenBefore(node); - if (precedingToken && util.isTokenOnSameLine(precedingToken, node)) { + if (precedingToken && isTokenOnSameLine(precedingToken, node)) { // eslint-disable-next-line deprecation/deprecation -- TODO - switch once our min ESLint version is 6.7.0 const hasSpace = sourceCode.isSpaceBetweenTokens( precedingToken, 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 e6015783a670..2f2a8c65117d 100644 --- a/packages/eslint-plugin/src/rules/space-before-function-paren.ts +++ b/packages/eslint-plugin/src/rules/space-before-function-paren.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule, isOpeningParenToken } from '../util'; type Option = 'always' | 'never'; type FuncOption = Option | 'ignore'; @@ -16,7 +16,7 @@ export type Options = [ ]; export type MessageIds = 'missing' | 'unexpected'; -export default util.createRule({ +export default createRule({ name: 'space-before-function-paren', meta: { type: 'layout', @@ -109,7 +109,7 @@ export default util.createRule({ // Always ignore non-async functions and arrow functions without parens, e.g. async foo => bar if ( node.async && - util.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 })!) + isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 })!) ) { return overrideConfig.asyncArrow ?? baseConfig; } @@ -149,10 +149,10 @@ export default util.createRule({ leftToken = sourceCode.getLastToken(node.typeParameters)!; rightToken = sourceCode.getTokenAfter(leftToken)!; } else { - rightToken = sourceCode.getFirstToken(node, util.isOpeningParenToken)!; + rightToken = sourceCode.getFirstToken(node, isOpeningParenToken)!; leftToken = sourceCode.getTokenBefore(rightToken)!; } - // eslint-disable-next-line deprecation/deprecation -- TODO - switch once our min ESLint version is 6.7.0 + const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken); if (hasSpacing && functionConfig === 'never') { diff --git a/packages/eslint-plugin/src/rules/space-infix-ops.ts b/packages/eslint-plugin/src/rules/space-infix-ops.ts index c1df490436fd..53df0b4e39d5 100644 --- a/packages/eslint-plugin/src/rules/space-infix-ops.ts +++ b/packages/eslint-plugin/src/rules/space-infix-ops.ts @@ -1,16 +1,20 @@ import { AST_TOKEN_TYPES, TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../util'; +import { createRule, isNotOpeningParenToken } from '../util'; import { getESLintCoreRule } from '../util/getESLintCoreRule'; const baseRule = getESLintCoreRule('space-infix-ops'); -export type Options = util.InferOptionsTypeFromRule; -export type MessageIds = util.InferMessageIdsTypeFromRule; +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; const UNIONS = ['|', '&']; -export default util.createRule({ +export default createRule({ name: 'space-infix-ops', meta: { type: 'layout', @@ -129,7 +133,7 @@ export default util.createRule({ types.forEach(type => { const skipFunctionParenthesis = type.type === TSESTree.AST_NODE_TYPES.TSFunctionType - ? util.isNotOpeningParenToken + ? isNotOpeningParenToken : 0; const operator = sourceCode.getTokenBefore( type, diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 2eed8cdc1e82..db0d4474a14c 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -6,7 +6,13 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; +import { + createRule, + getConstrainedTypeAtLocation, + getParserServices, + getWrappingFixer, + isTypeArrayTypeOrUnionOfArrayTypes, +} from '../util'; export type Options = [ { @@ -47,7 +53,7 @@ export type MessageId = | 'conditionFixDefaultZero' | 'noStrictNullCheck'; -export default util.createRule({ +export default createRule({ name: 'strict-boolean-expressions', meta: { type: 'suggestion', @@ -151,7 +157,7 @@ export default util.createRule({ }, ], create(context, [options]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const checker = services.program.getTypeChecker(); const compilerOptions = services.program.getCompilerOptions(); const sourceCode = context.getSourceCode(); @@ -267,7 +273,7 @@ export default util.createRule({ * It analyzes the type of a node and checks if it is allowed in a boolean context. */ function checkNode(node: TSESTree.Node): void { - const type = util.getConstrainedTypeAtLocation(services, node); + const type = getConstrainedTypeAtLocation(services, node); const types = inspectVariantTypes(tsutils.unionTypeParts(type)); const is = (...wantedTypes: readonly VariantType[]): boolean => @@ -309,7 +315,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixDefaultFalse', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} ?? false`, @@ -317,7 +323,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCompareFalse', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -334,7 +340,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixDefaultFalse', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} ?? false`, @@ -342,7 +348,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCompareTrue', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} === true`, @@ -374,7 +380,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareStringLength', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -383,7 +389,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCompareEmptyString', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -392,7 +398,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -409,7 +415,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareStringLength', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code}.length > 0`, @@ -417,7 +423,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCompareEmptyString', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} !== ""`, @@ -425,7 +431,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `Boolean(${code})`, @@ -449,7 +455,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareNullish', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -458,7 +464,7 @@ export default util.createRule({ }, { messageId: 'conditionFixDefaultEmptyString', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} ?? ""`, @@ -466,7 +472,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -483,7 +489,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareNullish', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} != null`, @@ -491,7 +497,7 @@ export default util.createRule({ }, { messageId: 'conditionFixDefaultEmptyString', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} ?? ""`, @@ -499,7 +505,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `Boolean(${code})`, @@ -521,7 +527,7 @@ export default util.createRule({ context.report({ node, messageId: 'conditionErrorNumber', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -533,7 +539,7 @@ export default util.createRule({ context.report({ node, messageId: 'conditionErrorNumber', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} > 0`, @@ -548,7 +554,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareZero', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -559,7 +565,7 @@ export default util.createRule({ { // TODO: don't suggest this for bigint because it can't be NaN messageId: 'conditionFixCompareNaN', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -568,7 +574,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -585,7 +591,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareZero', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} !== 0`, @@ -593,7 +599,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCompareNaN', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `!Number.isNaN(${code})`, @@ -601,7 +607,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `Boolean(${code})`, @@ -625,7 +631,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareNullish', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -634,7 +640,7 @@ export default util.createRule({ }, { messageId: 'conditionFixDefaultZero', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} ?? 0`, @@ -642,7 +648,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -659,7 +665,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareNullish', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} != null`, @@ -667,7 +673,7 @@ export default util.createRule({ }, { messageId: 'conditionFixDefaultZero', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} ?? 0`, @@ -675,7 +681,7 @@ export default util.createRule({ }, { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `Boolean(${code})`, @@ -706,7 +712,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareNullish', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -723,7 +729,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCompareNullish', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} != null`, @@ -753,7 +759,7 @@ export default util.createRule({ context.report({ node, messageId: 'conditionErrorNullableEnum', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node: node.parent, innerNode: node, @@ -764,7 +770,7 @@ export default util.createRule({ context.report({ node, messageId: 'conditionErrorNullableEnum', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `${code} != null`, @@ -784,7 +790,7 @@ export default util.createRule({ suggest: [ { messageId: 'conditionFixCastBoolean', - fix: util.getWrappingFixer({ + fix: getWrappingFixer({ sourceCode, node, wrap: code => `Boolean(${code})`, @@ -905,7 +911,7 @@ export default util.createRule({ if ( types.some(type => - util.isTypeFlagSet( + tsutils.isTypeFlagSet( type, ts.TypeFlags.TypeParameter | ts.TypeFlags.Any | @@ -945,6 +951,6 @@ function isArrayLengthExpression( if (node.property.name !== 'length') { return false; } - const objectType = util.getConstrainedTypeAtLocation(services, node.object); - return util.isTypeArrayTypeOrUnionOfArrayTypes(objectType, typeChecker); + const objectType = getConstrainedTypeAtLocation(services, node.object); + return isTypeArrayTypeOrUnionOfArrayTypes(objectType, typeChecker); } diff --git a/packages/eslint-plugin/src/rules/triple-slash-reference.ts b/packages/eslint-plugin/src/rules/triple-slash-reference.ts index 10f85b6cc6e6..22f6b49da617 100644 --- a/packages/eslint-plugin/src/rules/triple-slash-reference.ts +++ b/packages/eslint-plugin/src/rules/triple-slash-reference.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; type Options = [ { @@ -12,7 +12,7 @@ type Options = [ ]; type MessageIds = 'tripleSlashReference'; -export default util.createRule({ +export default createRule({ name: 'triple-slash-reference', meta: { type: 'suggestion', diff --git a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts index 20db2832184e..f9ca288649e0 100644 --- a/packages/eslint-plugin/src/rules/type-annotation-spacing.ts +++ b/packages/eslint-plugin/src/rules/type-annotation-spacing.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as util from '../util'; import { + createRule, isClassOrTypeElement, isFunction, isFunctionOrFunctionType, @@ -98,7 +98,7 @@ function getRules( return rules.colon; } -export default util.createRule({ +export default createRule({ name: 'type-annotation-spacing', meta: { type: 'layout', diff --git a/packages/eslint-plugin/src/rules/typedef.ts b/packages/eslint-plugin/src/rules/typedef.ts index 595081906afa..e84aaef8cb3d 100644 --- a/packages/eslint-plugin/src/rules/typedef.ts +++ b/packages/eslint-plugin/src/rules/typedef.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import { createRule } from '../util'; const enum OptionKeys { ArrayDestructuring = 'arrayDestructuring', @@ -18,7 +18,7 @@ type Options = { [k in OptionKeys]?: boolean }; type MessageIds = 'expectedTypedef' | 'expectedTypedefNamed'; -export default util.createRule<[Options], MessageIds>({ +export default createRule<[Options], MessageIds>({ name: 'typedef', meta: { docs: { diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index ce2ec6ccd735..e1c2aed6a019 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -3,8 +3,12 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import * as ts from 'typescript'; -import * as util from '../util'; -import { getModifiers } from '../util'; +import { + createRule, + getModifiers, + getParserServices, + isIdentifier, +} from '../util'; //------------------------------------------------------------------------------ // Rule Definition @@ -124,7 +128,7 @@ const getMemberFullName = (node: TSESTree.MemberExpression): string => const BASE_MESSAGE = 'Avoid referencing unbound methods which may cause unintentional scoping of `this`.'; -export default util.createRule({ +export default createRule({ name: 'unbound-method', meta: { docs: { @@ -161,7 +165,7 @@ export default util.createRule({ }, ], create(context, [{ ignoreStatic }]) { - const services = util.getParserServices(context); + const services = getParserServices(context); const currentSourceFile = services.program.getSourceFile( context.getFilename(), ); @@ -226,7 +230,7 @@ export default util.createRule({ ) { if ( notImported && - util.isIdentifier(initNode) && + isIdentifier(initNode) && nativelyBoundMembers.includes( `${initNode.name}.${property.key.name}`, ) diff --git a/packages/eslint-plugin/src/rules/unified-signatures.ts b/packages/eslint-plugin/src/rules/unified-signatures.ts index 34fb04c295ec..950125e8686f 100644 --- a/packages/eslint-plugin/src/rules/unified-signatures.ts +++ b/packages/eslint-plugin/src/rules/unified-signatures.ts @@ -1,7 +1,8 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as util from '../util'; +import type { Equal } from '../util'; +import { arraysAreEqual, createRule } from '../util'; interface Failure { unify: Unify; @@ -61,7 +62,7 @@ type Options = [ }, ]; -export default util.createRule({ +export default createRule({ name: 'unified-signatures', meta: { docs: { @@ -229,7 +230,7 @@ export default util.createRule({ typesAreEqual(a.returnType, b.returnType) && // Must take the same type parameters. // If one uses a type parameter (from outside) and the other doesn't, they shouldn't be joined. - util.arraysAreEqual(aTypeParams, bTypeParams, typeParametersAreEqual) && + arraysAreEqual(aTypeParams, bTypeParams, typeParametersAreEqual) && signatureUsesTypeParameter(a, isTypeParameter) === signatureUsesTypeParameter(b, isTypeParameter) ); @@ -251,7 +252,7 @@ export default util.createRule({ // If remaining arrays are equal, the signatures differ by just one parameter type if ( - !util.arraysAreEqual( + !arraysAreEqual( types1.slice(index + 1), types2.slice(index + 1), parametersAreEqual, @@ -462,7 +463,7 @@ export default util.createRule({ function getIndexOfFirstDifference( a: readonly T[], b: readonly T[], - equal: util.Equal, + equal: Equal, ): number | undefined { for (let i = 0; i < a.length && i < b.length; i++) { if (!equal(a[i], b[i])) { diff --git a/packages/eslint-plugin/tests/areOptionsValid.test.ts b/packages/eslint-plugin/tests/areOptionsValid.test.ts index 6ec3fd4dfca4..ab234f2fe3a8 100644 --- a/packages/eslint-plugin/tests/areOptionsValid.test.ts +++ b/packages/eslint-plugin/tests/areOptionsValid.test.ts @@ -1,7 +1,7 @@ -import * as util from '../src/util'; +import { createRule } from '../src/util'; import { areOptionsValid } from './areOptionsValid'; -const exampleRule = util.createRule<['value-a' | 'value-b'], never>({ +const exampleRule = createRule<['value-a' | 'value-b'], never>({ name: 'my-example-rule', meta: { type: 'layout', diff --git a/packages/eslint-plugin/tests/util.test.ts b/packages/eslint-plugin/tests/util.test.ts index a2f742870779..4242128b0687 100644 --- a/packages/eslint-plugin/tests/util.test.ts +++ b/packages/eslint-plugin/tests/util.test.ts @@ -1,4 +1,4 @@ -import * as util from '../src/util'; +import { isDefinitionFile, upperCaseFirst } from '../src/util'; describe('isDefinitionFile', () => { describe('returns false for non-definition files', () => { @@ -22,7 +22,7 @@ describe('isDefinitionFile', () => { invalid.forEach(f => { it(f, () => { - expect(util.isDefinitionFile(f)).toBe(false); + expect(isDefinitionFile(f)).toBe(false); }); }); }); @@ -32,7 +32,7 @@ describe('isDefinitionFile', () => { valid.forEach(f => { it(f, () => { - expect(util.isDefinitionFile(f)).toBe(true); + expect(isDefinitionFile(f)).toBe(true); }); }); }); @@ -40,6 +40,6 @@ describe('isDefinitionFile', () => { describe('upperCaseFirst', () => { it('upper cases first', () => { - expect(util.upperCaseFirst('hello')).toBe('Hello'); + expect(upperCaseFirst('hello')).toBe('Hello'); }); }); diff --git a/packages/eslint-plugin/tests/util/getWrappedCode.test.ts b/packages/eslint-plugin/tests/util/getWrappedCode.test.ts index 516642c16b57..bc57bfdabf09 100644 --- a/packages/eslint-plugin/tests/util/getWrappedCode.test.ts +++ b/packages/eslint-plugin/tests/util/getWrappedCode.test.ts @@ -2,7 +2,11 @@ import { RuleTester } from '@typescript-eslint/rule-tester'; import type { TSESTree } from '@typescript-eslint/utils'; import * as ts from 'typescript'; -import * as util from '../../src/util'; +import { + createRule, + getOperatorPrecedence, + getParserServices, +} from '../../src/util'; import { getWrappedCode } from '../../src/util/getWrappedCode'; import { getFixturesRootDir } from '../RuleTester'; @@ -15,7 +19,7 @@ const ruleTester = new RuleTester({ }, }); -const removeFunctionRule = util.createRule({ +const removeFunctionRule = createRule({ name: 'remove-function', defaultOptions: [], meta: { @@ -33,7 +37,7 @@ const removeFunctionRule = util.createRule({ create(context) { const sourceCode = context.getSourceCode(); - const parserServices = util.getParserServices(context, true); + const parserServices = getParserServices(context, true); const report = (node: TSESTree.CallExpression): void => { context.report({ @@ -43,13 +47,13 @@ const removeFunctionRule = util.createRule({ const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); const tsArgumentNode = tsNode.arguments[0]; - const nodePrecedence = util.getOperatorPrecedence( + const nodePrecedence = getOperatorPrecedence( tsArgumentNode.kind, ts.isBinaryExpression(tsArgumentNode) ? tsArgumentNode.operatorToken.kind : ts.SyntaxKind.Unknown, ); - const parentPrecedence = util.getOperatorPrecedence( + const parentPrecedence = getOperatorPrecedence( tsNode.parent.kind, ts.isBinaryExpression(tsNode.parent) ? tsNode.parent.operatorToken.kind From d683758403e6eec1454aac936dcc2de2d46a9826 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Tue, 10 Oct 2023 17:04:26 -0400 Subject: [PATCH 2/5] fix: revert isTypeFlagSet switch --- .../src/rules/no-unnecessary-type-assertion.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts index ba8ab57f1efb..6029cf192da3 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -10,6 +10,7 @@ import { getDeclaration, getParserServices, isNullableType, + isTypeFlagSet, } from '../util'; type Options = [ @@ -189,20 +190,17 @@ export default createRule({ if (contextualType) { // in strict mode you can't assign null to undefined, so we have to make sure that // the two types share a nullable type - const typeIncludesUndefined = tsutils.isTypeFlagSet( + const typeIncludesUndefined = isTypeFlagSet( type, ts.TypeFlags.Undefined, ); - const typeIncludesNull = tsutils.isTypeFlagSet( - type, - ts.TypeFlags.Null, - ); + const typeIncludesNull = isTypeFlagSet(type, ts.TypeFlags.Null); - const contextualTypeIncludesUndefined = tsutils.isTypeFlagSet( + const contextualTypeIncludesUndefined = isTypeFlagSet( contextualType, ts.TypeFlags.Undefined, ); - const contextualTypeIncludesNull = tsutils.isTypeFlagSet( + const contextualTypeIncludesNull = isTypeFlagSet( contextualType, ts.TypeFlags.Null, ); @@ -246,7 +244,7 @@ export default createRule({ const castType = services.getTypeAtLocation(node); if ( - tsutils.isTypeFlagSet(castType, ts.TypeFlags.Literal) || + isTypeFlagSet(castType, ts.TypeFlags.Literal) || (tsutils.isObjectType(castType) && (tsutils.isObjectFlagSet(castType, ts.ObjectFlags.Tuple) || couldBeTupleType(castType))) From 040dac6dc0ea26686f9d97cce211115c07ad0b4f Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 11 Oct 2023 12:44:23 +0800 Subject: [PATCH 3/5] chore: conflicts --- .../src/rules/prefer-optional-chain-utils/analyzeChain.ts | 3 ++- .../rules/prefer-optional-chain-utils/gatherLogicalOperands.ts | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts index 5e0508925a47..dea7b6f490b7 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/analyzeChain.ts @@ -9,12 +9,13 @@ import type { RuleContext, SourceCode, } from '@typescript-eslint/utils/ts-eslint'; -import { isTypeFlagSet, unionTypeParts } from 'ts-api-utils'; +import { unionTypeParts } from 'ts-api-utils'; import * as ts from 'typescript'; import { getOperatorPrecedenceForNode, isOpeningParenToken, + isTypeFlagSet, nullThrows, NullThrowsReasons, OperatorPrecedence, diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts index a9fd4055a927..73ce6d9255aa 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain-utils/gatherLogicalOperands.ts @@ -8,12 +8,11 @@ import { isBooleanLiteralType, isNumberLiteralType, isStringLiteralType, - isTypeFlagSet, unionTypeParts, } from 'ts-api-utils'; import * as ts from 'typescript'; -import {} from '../../util'; +import { isTypeFlagSet } from '../../util'; import type { PreferOptionalChainOptions } from './PreferOptionalChainOptions'; const enum ComparisonValueType { From e4859d618c61cdb35001bbae0e126e6d2198714d Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 11 Oct 2023 16:20:38 +0800 Subject: [PATCH 4/5] chore: adding back comments --- packages/eslint-plugin/src/rules/no-magic-numbers.ts | 1 + packages/eslint-plugin/src/rules/space-before-function-paren.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 67083f27e287..54e559d3365c 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -16,6 +16,7 @@ type MessageIds = InferMessageIdsTypeFromRule; // Extend base schema with additional property to ignore TS numeric literal types const schema = deepMerge( + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- https://github.com/microsoft/TypeScript/issues/17002 Array.isArray(baseRule.meta.schema) ? baseRule.meta.schema[0] : baseRule.meta.schema, 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 2f2a8c65117d..b7d5458b041e 100644 --- a/packages/eslint-plugin/src/rules/space-before-function-paren.ts +++ b/packages/eslint-plugin/src/rules/space-before-function-paren.ts @@ -153,6 +153,7 @@ export default createRule({ leftToken = sourceCode.getTokenBefore(rightToken)!; } + // eslint-disable-next-line deprecation/deprecation -- TODO - switch once our min ESLint version is 6.7.0 const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken); if (hasSpacing && functionConfig === 'never') { From 05b5cabec66d64a7e8850adea5e9e29f43fa6941 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 11 Oct 2023 16:42:11 +0800 Subject: [PATCH 5/5] fix: conflicts --- packages/eslint-plugin/src/rules/restrict-plus-operands.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index 99c331bbae4e..9e17fa486b52 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -8,6 +8,7 @@ import { getParserServices, getTypeName, isTypeAnyType, + isTypeFlagSet, } from '../util'; type Options = [ @@ -156,10 +157,7 @@ export default createRule({ (!allowBoolean && isTypeFlagSetInUnion(baseType, ts.TypeFlags.BooleanLike)) || (!allowNullish && - tsutils.isTypeFlagSet( - baseType, - ts.TypeFlags.Null | ts.TypeFlags.Undefined, - )) + isTypeFlagSet(baseType, ts.TypeFlags.Null | ts.TypeFlags.Undefined)) ) { context.report({ data: {