From 79327b4999999cde3003901b40527af002c4906a Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 6 Feb 2023 04:01:35 -0500 Subject: [PATCH] fix: replace tsutils with ts-api-tools (#6428) * fix: replace tsutils with ts-api-tools * Prefer .cjs files in tests over .js (for ts-api-tools) * ts-api-tools@0.0.15 * ur welcome * that too --- .cspell.json | 1 - docs/Custom_Rules.mdx | 4 +- jest.config.base.js | 1 + packages/eslint-plugin/package.json | 2 +- .../eslint-plugin/src/rules/await-thenable.ts | 4 +- .../eslint-plugin/src/rules/dot-notation.ts | 4 +- .../src/rules/no-confusing-void-expression.ts | 4 +- .../src/rules/no-dynamic-delete.ts | 4 +- .../src/rules/no-floating-promises.ts | 10 ++-- .../src/rules/no-implied-eval.ts | 4 +- .../src/rules/no-meaningless-void-operator.ts | 4 +- .../src/rules/no-misused-promises.ts | 24 ++++----- .../rules/no-redundant-type-constituents.ts | 12 ++--- .../no-unnecessary-boolean-literal-compare.ts | 6 +-- .../src/rules/no-unnecessary-condition.ts | 53 +++++++++---------- .../src/rules/no-unnecessary-qualifier.ts | 4 +- .../rules/no-unnecessary-type-arguments.ts | 4 +- .../rules/no-unnecessary-type-assertion.ts | 21 ++++---- .../src/rules/no-unsafe-assignment.ts | 4 +- .../eslint-plugin/src/rules/no-unsafe-call.ts | 4 +- .../src/rules/no-unsafe-member-access.ts | 4 +- .../src/rules/no-unsafe-return.ts | 6 +-- .../non-nullable-type-assertion-style.ts | 10 ++-- .../src/rules/prefer-nullish-coalescing.ts | 4 +- .../src/rules/prefer-optional-chain.ts | 3 +- .../src/rules/prefer-readonly.ts | 22 ++++---- .../src/rules/prefer-regexp-exec.ts | 4 +- .../eslint-plugin/src/rules/require-await.ts | 6 +-- .../eslint-plugin/src/rules/return-await.ts | 7 ++- .../src/rules/strict-boolean-expressions.ts | 22 ++++---- .../src/rules/switch-exhaustiveness-check.ts | 6 +-- .../eslint-plugin/src/rules/unbound-method.ts | 5 +- packages/type-utils/package.json | 2 +- .../type-utils/src/containsAllTypesByName.ts | 6 +-- packages/type-utils/src/getContextualType.ts | 26 +++------ packages/type-utils/src/isTypeReadonly.ts | 40 +++++++------- packages/type-utils/src/isUnsafeAssignment.ts | 4 +- packages/type-utils/src/predicates.ts | 4 +- packages/type-utils/src/typeFlagUtils.ts | 4 +- packages/typescript-estree/package.json | 2 +- .../typescript-estree/src/convert-comments.ts | 4 +- patches/tsutils+3.21.0.patch | 13 ----- yarn.lock | 5 ++ 43 files changed, 176 insertions(+), 207 deletions(-) delete mode 100644 patches/tsutils+3.21.0.patch diff --git a/.cspell.json b/.cspell.json index 21ca6f8fc23..3ee9e639f2e 100644 --- a/.cspell.json +++ b/.cspell.json @@ -114,7 +114,6 @@ "triaging", "tsconfigs", "tseslint", - "tsutils", "tsvfs", "typedef", "typedefs", diff --git a/docs/Custom_Rules.mdx b/docs/Custom_Rules.mdx index a635d93c989..cce54c78ad6 100644 --- a/docs/Custom_Rules.mdx +++ b/docs/Custom_Rules.mdx @@ -230,8 +230,8 @@ This rule bans for-of looping over an enum by using the TypeScript type checker ```ts import { ESLintUtils } from '@typescript-eslint/utils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; -import * as tsutils from 'tsutils'; export const rule = createRule({ create(context) { @@ -244,7 +244,7 @@ export const rule = createRule({ const type = services.getTypeAtLocation(node); // 3. Check the TS type using the TypeScript APIs - if (tsutils.isTypeFlagSet(nodeType, ts.TypeFlags.EnumLike)) { + if (tools.isTypeFlagSet(nodeType, ts.TypeFlags.EnumLike)) { context.report({ messageId: 'loopOverEnum', node: node.right, diff --git a/jest.config.base.js b/jest.config.base.js index 707c023f269..1adc8f85596 100644 --- a/jest.config.base.js +++ b/jest.config.base.js @@ -11,6 +11,7 @@ module.exports = { 'tsx', 'mts', 'mtsx', + 'cjs', 'js', 'jsx', 'mjs', diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index f7580cf43bb..fdfa8f35a50 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -53,7 +53,7 @@ "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ts-api-tools": "^0.0.15" }, "devDependencies": { "@types/debug": "*", diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 2e41aab2ea1..33678990522 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,4 +1,4 @@ -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as util from '../util'; @@ -31,7 +31,7 @@ export default util.createRule({ const originalNode = services.esTreeNodeToTSNodeMap.get(node); - if (!tsutils.isThenableType(checker, originalNode.expression, type)) { + if (!tools.isThenableType(checker, originalNode.expression, type)) { context.report({ messageId: 'await', node, diff --git a/packages/eslint-plugin/src/rules/dot-notation.ts b/packages/eslint-plugin/src/rules/dot-notation.ts index b94f6bc68e6..df6a502115d 100644 --- a/packages/eslint-plugin/src/rules/dot-notation.ts +++ b/packages/eslint-plugin/src/rules/dot-notation.ts @@ -1,5 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import type { @@ -75,7 +75,7 @@ export default createRule({ options.allowProtectedClassPropertyAccess; const allowIndexSignaturePropertyAccess = (options.allowIndexSignaturePropertyAccess ?? false) || - tsutils.isCompilerOptionEnabled( + tools.isCompilerOptionEnabled( services.program.getCompilerOptions(), // @ts-expect-error - TS is refining the type to never for some reason 'noPropertyAccessFromIndexSignature', 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 a54bd46a80a..77bdb724ef9 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -82,7 +82,7 @@ export default util.createRule({ ): void { const services = util.getParserServices(context); const type = util.getConstrainedTypeAtLocation(services, node); - if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { + if (!tools.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; } diff --git a/packages/eslint-plugin/src/rules/no-dynamic-delete.ts b/packages/eslint-plugin/src/rules/no-dynamic-delete.ts index 09d5b5420d8..325508ff9b6 100644 --- a/packages/eslint-plugin/src/rules/no-dynamic-delete.ts +++ b/packages/eslint-plugin/src/rules/no-dynamic-delete.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as util from '../util'; @@ -97,6 +97,6 @@ function isNecessaryDynamicAccess(property: TSESTree.Expression): boolean { return ( typeof property.value === 'string' && - !tsutils.isValidPropertyAccess(property.value) + !tools.isValidPropertyAccess(property.value) ); } diff --git a/packages/eslint-plugin/src/rules/no-floating-promises.ts b/packages/eslint-plugin/src/rules/no-floating-promises.ts index d6e61e458d5..21006caf137 100644 --- a/packages/eslint-plugin/src/rules/no-floating-promises.ts +++ b/packages/eslint-plugin/src/rules/no-floating-promises.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -148,7 +148,7 @@ export default util.createRule({ }; function isHigherPrecedenceThanUnary(node: ts.Node): boolean { - const operator = tsutils.isBinaryExpression(node) + const operator = ts.isBinaryExpression(node) ? node.operatorToken.kind : ts.SyntaxKind.Unknown; const nodePrecedence = util.getOperatorPrecedence(node.kind, operator); @@ -240,7 +240,7 @@ export default util.createRule({ // https://github.com/ajafff/tsutils/blob/49d0d31050b44b81e918eae4fbaf1dfe7b7286af/util/type.ts#L95-L125 function isPromiseLike(checker: ts.TypeChecker, node: ts.Node): boolean { const type = checker.getTypeAtLocation(node); - for (const ty of tsutils.unionTypeParts(checker.getApparentType(type))) { + for (const ty of tools.unionTypeParts(checker.getApparentType(type))) { const then = ty.getProperty('then'); if (then === undefined) { continue; @@ -266,7 +266,7 @@ function hasMatchingSignature( type: ts.Type, matcher: (signature: ts.Signature) => boolean, ): boolean { - for (const t of tsutils.unionTypeParts(type)) { + for (const t of tools.unionTypeParts(type)) { if (t.getCallSignatures().some(matcher)) { return true; } @@ -283,7 +283,7 @@ function isFunctionParam( const type: ts.Type | undefined = checker.getApparentType( checker.getTypeOfSymbolAtLocation(param, node), ); - for (const t of tsutils.unionTypeParts(type)) { + for (const t of tools.unionTypeParts(type)) { if (t.getCallSignatures().length !== 0) { return true; } diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index c1cdcfbbd21..f14742a3c7a 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -69,7 +69,7 @@ export default util.createRule({ if ( symbol && - tsutils.isSymbolFlagSet( + tools.isSymbolFlagSet( symbol, ts.SymbolFlags.Function | ts.SymbolFlags.Method, ) 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 c585b13f785..7cfb1822fc7 100644 --- a/packages/eslint-plugin/src/rules/no-meaningless-void-operator.ts +++ b/packages/eslint-plugin/src/rules/no-meaningless-void-operator.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { ESLintUtils } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -61,7 +61,7 @@ export default util.createRule< }; const argType = services.getTypeAtLocation(node.argument); - const unionParts = tsutils.unionTypeParts(argType); + const unionParts = tools.unionTypeParts(argType); if ( unionParts.every( part => part.flags & (ts.TypeFlags.Void | ts.TypeFlags.Undefined), diff --git a/packages/eslint-plugin/src/rules/no-misused-promises.ts b/packages/eslint-plugin/src/rules/no-misused-promises.ts index 9d0e3b4a639..21f32539603 100644 --- a/packages/eslint-plugin/src/rules/no-misused-promises.ts +++ b/packages/eslint-plugin/src/rules/no-misused-promises.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -410,8 +410,8 @@ export default util.createRule({ function isSometimesThenable(checker: ts.TypeChecker, node: ts.Node): boolean { const type = checker.getTypeAtLocation(node); - for (const subType of tsutils.unionTypeParts(checker.getApparentType(type))) { - if (tsutils.isThenableType(checker, node, subType)) { + for (const subType of tools.unionTypeParts(checker.getApparentType(type))) { + if (tools.isThenableType(checker, node, subType)) { return true; } } @@ -426,7 +426,7 @@ function isSometimesThenable(checker: ts.TypeChecker, node: ts.Node): boolean { function isAlwaysThenable(checker: ts.TypeChecker, node: ts.Node): boolean { const type = checker.getTypeAtLocation(node); - for (const subType of tsutils.unionTypeParts(checker.getApparentType(type))) { + for (const subType of tools.unionTypeParts(checker.getApparentType(type))) { const thenProp = subType.getProperty('then'); // If one of the alternates has no then property, it is not thenable in all @@ -440,7 +440,7 @@ function isAlwaysThenable(checker: ts.TypeChecker, node: ts.Node): boolean { // be of the right form to consider it thenable. const thenType = checker.getTypeOfSymbolAtLocation(thenProp, node); let hasThenableSignature = false; - for (const subType of tsutils.unionTypeParts(thenType)) { + for (const subType of tools.unionTypeParts(thenType)) { for (const signature of subType.getCallSignatures()) { if ( signature.parameters.length !== 0 && @@ -478,7 +478,7 @@ function isFunctionParam( const type: ts.Type | undefined = checker.getApparentType( checker.getTypeOfSymbolAtLocation(param, node), ); - for (const subType of tsutils.unionTypeParts(type)) { + for (const subType of tools.unionTypeParts(type)) { if (subType.getCallSignatures().length !== 0) { return true; } @@ -527,7 +527,7 @@ function voidFunctionArguments( // We can't use checker.getResolvedSignature because it prefers an early '() => void' over a later '() => Promise' // See https://github.com/microsoft/TypeScript/issues/48077 - for (const subType of tsutils.unionTypeParts(type)) { + for (const subType of tools.unionTypeParts(type)) { // Standard function calls and `new` have two different types of signatures const signatures = ts.isCallExpression(node) ? subType.getCallSignatures() @@ -610,7 +610,7 @@ function anySignatureIsThenableType( ): boolean { for (const signature of type.getCallSignatures()) { const returnType = signature.getReturnType(); - if (tsutils.isThenableType(checker, node, returnType)) { + if (tools.isThenableType(checker, node, returnType)) { return true; } } @@ -626,7 +626,7 @@ function isThenableReturningFunctionType( node: ts.Node, type: ts.Type, ): boolean { - for (const subType of tsutils.unionTypeParts(type)) { + for (const subType of tools.unionTypeParts(type)) { if (anySignatureIsThenableType(checker, node, subType)) { return true; } @@ -645,17 +645,17 @@ function isVoidReturningFunctionType( ): boolean { let hadVoidReturn = false; - for (const subType of tsutils.unionTypeParts(type)) { + for (const subType of tools.unionTypeParts(type)) { for (const signature of subType.getCallSignatures()) { const returnType = signature.getReturnType(); // If a certain positional argument accepts both thenable and void returns, // a promise-returning function is valid - if (tsutils.isThenableType(checker, node, returnType)) { + if (tools.isThenableType(checker, node, returnType)) { return false; } - hadVoidReturn ||= tsutils.isTypeFlagSet(returnType, ts.TypeFlags.Void); + hadVoidReturn ||= tools.isTypeFlagSet(returnType, ts.TypeFlags.Void); } } 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 db015edc839..ae5af074b0b 100644 --- a/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts +++ b/packages/eslint-plugin/src/rules/no-redundant-type-constituents.ts @@ -1,5 +1,5 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -106,11 +106,11 @@ function describeLiteralType(type: ts.Type): string { return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`; } - if (tsutils.isBooleanLiteralType(type, true)) { + if (tools.isBooleanLiteralType(type, true)) { return 'true'; } - if (tsutils.isBooleanLiteralType(type, false)) { + if (tools.isBooleanLiteralType(type, false)) { return 'false'; } @@ -166,10 +166,10 @@ function isNodeInsideReturnType(node: TSESTree.TSUnionType): boolean { function unionTypePartsUnlessBoolean(type: ts.Type): ts.Type[] { return type.isUnion() && type.types.length === 2 && - tsutils.isBooleanLiteralType(type.types[0], false) && - tsutils.isBooleanLiteralType(type.types[1], true) + tools.isBooleanLiteralType(type.types[0], false) && + tools.isBooleanLiteralType(type.types[1], true) ? [type] - : tsutils.unionTypeParts(type); + : tools.unionTypeParts(type); } export default util.createRule({ 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 97b05a210ac..36cdd33f7ef 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 @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -110,7 +110,7 @@ export default util.createRule({ } function isBooleanType(expressionType: ts.Type): boolean { - return tsutils.isTypeFlagSet( + return tools.isTypeFlagSet( expressionType, ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral, ); @@ -131,7 +131,7 @@ export default util.createRule({ const nonNullishTypes = types.filter( type => - !tsutils.isTypeFlagSet( + !tools.isTypeFlagSet( type, ts.TypeFlags.Undefined | ts.TypeFlags.Null, ), diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index e3a9e95afbe..14f80ffc8e1 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -1,13 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import { - getCallSignaturesOfType, - isBooleanLiteralType, - isFalsyType, - isLiteralType, - isStrictCompilerOptionEnabled, - unionTypeParts, -} from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import { @@ -28,17 +21,19 @@ import { // Truthiness utilities // #region const isTruthyLiteral = (type: ts.Type): boolean => - isBooleanLiteralType(type, true) || (isLiteralType(type) && !!type.value); + tools.isBooleanLiteralType(type, true) || + (tools.isLiteralType(type) && !!type.value); const isPossiblyFalsy = (type: ts.Type): boolean => - unionTypeParts(type) + tools + .unionTypeParts(type) // PossiblyFalsy flag includes literal values, so exclude ones that // are definitely truthy .filter(t => !isTruthyLiteral(t)) .some(type => isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); const isPossiblyTruthy = (type: ts.Type): boolean => - unionTypeParts(type).some(type => !isFalsyType(type)); + tools.unionTypeParts(type).some(type => !tools.isFalsyType(type)); // Nullish utilities const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; @@ -46,19 +41,19 @@ const isNullishType = (type: ts.Type): boolean => isTypeFlagSet(type, nullishFlag); const isPossiblyNullish = (type: ts.Type): boolean => - unionTypeParts(type).some(isNullishType); + tools.unionTypeParts(type).some(isNullishType); const isAlwaysNullish = (type: ts.Type): boolean => - unionTypeParts(type).every(isNullishType); + tools.unionTypeParts(type).every(isNullishType); // isLiteralType only covers numbers and strings, this is a more exhaustive check. const isLiteral = (type: ts.Type): boolean => - isBooleanLiteralType(type, true) || - isBooleanLiteralType(type, false) || + tools.isBooleanLiteralType(type, true) || + tools.isBooleanLiteralType(type, false) || type.flags === ts.TypeFlags.Undefined || type.flags === ts.TypeFlags.Null || type.flags === ts.TypeFlags.Void || - isLiteralType(type); + tools.isLiteralType(type); // #endregion export type Options = [ @@ -150,7 +145,7 @@ export default createRule({ const checker = services.program.getTypeChecker(); const sourceCode = context.getSourceCode(); const compilerOptions = services.program.getCompilerOptions(); - const isStrictNullChecks = isStrictCompilerOptionEnabled( + const isStrictNullChecks = tools.isStrictCompilerOptionEnabled( compilerOptions, 'strictNullChecks', ); @@ -232,12 +227,14 @@ export default createRule({ // Conditional is always necessary if it involves: // `any` or `unknown` or a naked type parameter if ( - unionTypeParts(type).some( - part => - isTypeAnyType(part) || - isTypeUnknownType(part) || - isTypeFlagSet(part, ts.TypeFlags.TypeParameter), - ) + tools + .unionTypeParts(type) + .some( + part => + isTypeAnyType(part) || + isTypeUnknownType(part) || + isTypeFlagSet(part, ts.TypeFlags.TypeParameter), + ) ) { return; } @@ -392,7 +389,7 @@ export default createRule({ */ if ( allowConstantLoopConditions && - isBooleanLiteralType( + tools.isBooleanLiteralType( getConstrainedTypeAtLocation(services, node.test), true, ) @@ -449,9 +446,11 @@ export default createRule({ // (Value to complexity ratio is dubious however) } // Otherwise just do type analysis on the function as a whole. - const returnTypes = getCallSignaturesOfType( - getConstrainedTypeAtLocation(services, callback), - ).map(sig => sig.getReturnType()); + const returnTypes = tools + .getCallSignaturesOfType( + getConstrainedTypeAtLocation(services, callback), + ) + .map(sig => sig.getReturnType()); /* istanbul ignore if */ if (returnTypes.length === 0) { // Not a callable function return; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index 4265dc3d24c..56c491e05b0 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -34,7 +34,7 @@ export default util.createRule({ symbol: ts.Symbol, checker: ts.TypeChecker, ): ts.Symbol | null { - return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) + return tools.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) ? checker.getAliasedSymbol(symbol) : null; } 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 1860e26a8bd..2508b0ddaf7 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-arguments.ts @@ -1,5 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -179,7 +179,7 @@ function getAliasedSymbol( symbol: ts.Symbol, checker: ts.TypeChecker, ): ts.Symbol { - return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) + return tools.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) ? checker.getAliasedSymbol(symbol) : symbol; } 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 87ef3b9ba42..6dc0cefabdc 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -1,12 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import { - isObjectFlagSet, - isObjectType, - isStrictCompilerOptionEnabled, - isTypeFlagSet, - isVariableDeclaration, -} from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -100,10 +94,13 @@ export default util.createRule({ if ( // non-strict mode doesn't care about used before assigned errors - isStrictCompilerOptionEnabled(compilerOptions, 'strictNullChecks') && + tools.isStrictCompilerOptionEnabled( + compilerOptions, + 'strictNullChecks', + ) && // ignore class properties as they are compile time guarded // also ignore function arguments as they can't be used before defined - isVariableDeclaration(declaration) && + ts.isVariableDeclaration(declaration) && // is it `const x!: number` declaration.initializer === undefined && declaration.exclamationToken === undefined && @@ -244,9 +241,9 @@ export default util.createRule({ const castType = services.getTypeAtLocation(node); if ( - isTypeFlagSet(castType, ts.TypeFlags.Literal) || - (isObjectType(castType) && - (isObjectFlagSet(castType, ts.ObjectFlags.Tuple) || + tools.isTypeFlagSet(castType, ts.TypeFlags.Literal) || + (tools.isObjectType(castType) && + (tools.isObjectFlagSet(castType, ts.ObjectFlags.Tuple) || couldBeTupleType(castType))) ) { // It's not always safe to remove a cast to a literal type or tuple diff --git a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts index 01cd90b20b8..c3e3d432f36 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import type * as ts from 'typescript'; import * as util from '../util'; @@ -45,7 +45,7 @@ export default util.createRule({ const services = util.getParserServices(context); const checker = services.program.getTypeChecker(); const compilerOptions = services.program.getCompilerOptions(); - const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( + const isNoImplicitThis = tools.isStrictCompilerOptionEnabled( compilerOptions, 'noImplicitThis', ); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-call.ts b/packages/eslint-plugin/src/rules/no-unsafe-call.ts index 216339d26b0..9b2c08cb10e 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-call.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-call.ts @@ -1,5 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as util from '../util'; import { getThisExpression } from '../util'; @@ -34,7 +34,7 @@ export default util.createRule<[], MessageIds>({ create(context) { const services = util.getParserServices(context); const compilerOptions = services.program.getCompilerOptions(); - const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( + const isNoImplicitThis = tools.isStrictCompilerOptionEnabled( compilerOptions, 'noImplicitThis', ); 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 a0858af39e4..cc8f57bb4f3 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as util from '../util'; import { getThisExpression } from '../util'; @@ -35,7 +35,7 @@ export default util.createRule({ create(context) { const services = util.getParserServices(context); const compilerOptions = services.program.getCompilerOptions(); - const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( + const isNoImplicitThis = tools.isStrictCompilerOptionEnabled( compilerOptions, 'noImplicitThis', ); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-return.ts b/packages/eslint-plugin/src/rules/no-unsafe-return.ts index 7843f25ffa1..dc10a68b73b 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-return.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-return.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as util from '../util'; import { getThisExpression } from '../util'; @@ -30,7 +30,7 @@ export default util.createRule({ const services = util.getParserServices(context); const checker = services.program.getTypeChecker(); const compilerOptions = services.program.getCompilerOptions(); - const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled( + const isNoImplicitThis = tools.isStrictCompilerOptionEnabled( compilerOptions, 'noImplicitThis', ); @@ -82,7 +82,7 @@ export default util.createRule({ // so we have to use the contextual typing in these cases, i.e. // const foo1: () => Set = () => new Set(); // the return type of the arrow function is Set even though the variable is typed as Set - let functionType = tsutils.isExpression(functionTSNode) + let functionType = tools.isExpression(functionTSNode) ? util.getContextualType(checker, functionTSNode) : services.getTypeAtLocation(functionNode); if (!functionType) { 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 b42a1c06d40..bda463dd7d9 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 @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -30,20 +30,18 @@ export default util.createRule({ const getTypesIfNotLoose = (node: TSESTree.Node): ts.Type[] | undefined => { const type = services.getTypeAtLocation(node); - if ( - tsutils.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown) - ) { + if (tools.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { return undefined; } - return tsutils.unionTypeParts(type); + return tools.unionTypeParts(type); }; const couldBeNullish = (type: ts.Type): boolean => { if (type.flags & ts.TypeFlags.TypeParameter) { const constraint = type.getConstraint(); return constraint == null || couldBeNullish(constraint); - } else if (tsutils.isUnionType(type)) { + } else if (tools.isUnionType(type)) { for (const part of type.types) { if (couldBeNullish(part)) { return true; diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index 28ec95e5a73..af72186360c 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -83,7 +83,7 @@ export default util.createRule({ const services = util.getParserServices(context); const compilerOptions = services.program.getCompilerOptions(); const sourceCode = context.getSourceCode(); - const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled( + const isStrictNullChecks = tools.isStrictCompilerOptionEnabled( compilerOptions, 'strictNullChecks', ); diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index 95b910e7909..767c235ec08 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -1,6 +1,5 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import { isBinaryExpression } from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -76,7 +75,7 @@ export default util.createRule({ const logicalTsNode = services.esTreeNodeToTSNodeMap.get(node); const leftTsNode = services.esTreeNodeToTSNodeMap.get(leftNode); - const operator = isBinaryExpression(logicalTsNode) + const operator = ts.isBinaryExpression(logicalTsNode) ? logicalTsNode.operatorToken.kind : ts.SyntaxKind.Unknown; const leftPrecedence = util.getOperatorPrecedence( diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 64d6adb5e89..931fae7f6e0 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES, ASTUtils } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -83,7 +83,7 @@ export default util.createRule({ ): void { if ( parent.left === node && - tsutils.isAssignmentKind(parent.operatorToken.kind) + tools.isAssignmentKind(parent.operatorToken.kind) ) { classScope.addVariableModification(node); } @@ -141,7 +141,7 @@ export default util.createRule({ | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.MethodDefinition, - ): boolean | tsutils.ScopeBoundary { + ): boolean | tools.ScopeBoundary { if (classScopeStack.length === 0) { return false; } @@ -151,7 +151,7 @@ export default util.createRule({ return false; } - return tsutils.isFunctionScopeBoundary(tsNode); + return tools.isFunctionScopeBoundary(tsNode); } function getEsNodesFromViolatingNode( @@ -274,7 +274,7 @@ class ClassScope { private readonly onlyInlineLambdas?: boolean, ) { const classType = checker.getTypeAtLocation(classNode); - if (tsutils.isIntersectionType(classType)) { + if (tools.isIntersectionType(classType)) { this.classType = classType.types[0]; } else { this.classType = classType; @@ -289,8 +289,8 @@ class ClassScope { public addDeclaredVariable(node: ParameterOrPropertyDeclaration): void { if ( - !tsutils.isModifierFlagSet(node, ts.ModifierFlags.Private) || - tsutils.isModifierFlagSet(node, ts.ModifierFlags.Readonly) || + !tools.isModifierFlagSet(node, ts.ModifierFlags.Private) || + tools.isModifierFlagSet(node, ts.ModifierFlags.Readonly) || ts.isComputedPropertyName(node.name) ) { return; @@ -304,7 +304,7 @@ class ClassScope { return; } - (tsutils.isModifierFlagSet(node, ts.ModifierFlags.Static) + (tools.isModifierFlagSet(node, ts.ModifierFlags.Static) ? this.privateModifiableStatics : this.privateModifiableMembers ).set(node.name.getText(), node); @@ -320,8 +320,8 @@ class ClassScope { } const modifyingStatic = - tsutils.isObjectType(modifierType) && - tsutils.isObjectFlagSet(modifierType, ts.ObjectFlags.Anonymous); + tools.isObjectType(modifierType) && + tools.isObjectFlagSet(modifierType, ts.ObjectFlags.Anonymous); if ( !modifyingStatic && this.constructorScopeDepth === DIRECTLY_INSIDE_CONSTRUCTOR @@ -345,7 +345,7 @@ class ClassScope { this.constructorScopeDepth = DIRECTLY_INSIDE_CONSTRUCTOR; for (const parameter of node.parameters) { - if (tsutils.isModifierFlagSet(parameter, ts.ModifierFlags.Private)) { + if (tools.isModifierFlagSet(parameter, ts.ModifierFlags.Private)) { this.addDeclaredVariable(parameter); } } diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index 413eae49774..df72cfda39a 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import type * as ts from 'typescript'; import { @@ -134,7 +134,7 @@ export default createRule({ const argumentType = services.getTypeAtLocation(argumentNode); const argumentTypes = collectArgumentTypes( - tsutils.unionTypeParts(argumentType), + tools.unionTypeParts(argumentType), ); switch (argumentTypes) { case ArgumentType.RegExp: diff --git a/packages/eslint-plugin/src/rules/require-await.ts b/packages/eslint-plugin/src/rules/require-await.ts index c9437b4dc7c..96d1f741e8d 100644 --- a/packages/eslint-plugin/src/rules/require-await.ts +++ b/packages/eslint-plugin/src/rules/require-await.ts @@ -1,6 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import type * as ts from 'typescript'; import * as util from '../util'; @@ -88,7 +88,7 @@ export default util.createRule({ function isThenableType(node: ts.Node): boolean { const type = checker.getTypeAtLocation(node); - return tsutils.isThenableType(checker, node, type); + return tools.isThenableType(checker, node, type); } /** @@ -119,7 +119,7 @@ export default util.createRule({ const type = services.getTypeAtLocation(node.argument); const typesToCheck = expandUnionOrIntersectionType(type); for (const type of typesToCheck) { - const asyncIterator = tsutils.getWellKnownSymbolPropertyOfType( + const asyncIterator = tools.getWellKnownSymbolPropertyOfType( type, 'asyncIterator', checker, diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index cddfc4ba8c7..ce71a6bf506 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -1,7 +1,6 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; -import { isBinaryExpression } from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -166,7 +165,7 @@ export default util.createRule({ } function isHigherPrecedenceThanAwait(node: ts.Node): boolean { - const operator = isBinaryExpression(node) + const operator = ts.isBinaryExpression(node) ? node.operatorToken.kind : ts.SyntaxKind.Unknown; const nodePrecedence = getOperatorPrecedence(node.kind, operator); @@ -189,7 +188,7 @@ export default util.createRule({ } const type = checker.getTypeAtLocation(child); - const isThenable = tsutils.isThenableType(checker, expression, type); + const isThenable = tools.isThenableType(checker, expression, type); if (!isAwait && !isThenable) { return; diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index b7a18b87cd5..9812491adf4 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -3,7 +3,7 @@ import type { TSESTree, } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -149,7 +149,7 @@ export default util.createRule({ const checker = services.program.getTypeChecker(); const compilerOptions = services.program.getCompilerOptions(); const sourceCode = context.getSourceCode(); - const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled( + const isStrictNullChecks = tools.isStrictCompilerOptionEnabled( compilerOptions, 'strictNullChecks', ); @@ -262,7 +262,7 @@ export default util.createRule({ */ function checkNode(node: TSESTree.Node): void { const type = util.getConstrainedTypeAtLocation(services, node); - const types = inspectVariantTypes(tsutils.unionTypeParts(type)); + const types = inspectVariantTypes(tools.unionTypeParts(type)); const is = (...wantedTypes: readonly VariantType[]): boolean => types.size === wantedTypes.length && @@ -766,7 +766,7 @@ export default util.createRule({ if ( types.some(type => - tsutils.isTypeFlagSet( + tools.isTypeFlagSet( type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike, ), @@ -775,15 +775,15 @@ export default util.createRule({ variantTypes.add('nullish'); } const booleans = types.filter(type => - tsutils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), + tools.isTypeFlagSet(type, ts.TypeFlags.BooleanLike), ); // If incoming type is either "true" or "false", there will be one type // object with intrinsicName set accordingly // If incoming type is boolean, there will be two type objects with - // intrinsicName set "true" and "false" each because of tsutils.unionTypeParts() + // intrinsicName set "true" and "false" each because of ts-api-tools.unionTypeParts() if (booleans.length === 1) { - tsutils.isBooleanLiteralType(booleans[0], true) + tools.isBooleanLiteralType(booleans[0], true) ? variantTypes.add('truthy boolean') : variantTypes.add('boolean'); } else if (booleans.length === 2) { @@ -791,7 +791,7 @@ export default util.createRule({ } const strings = types.filter(type => - tsutils.isTypeFlagSet(type, ts.TypeFlags.StringLike), + tools.isTypeFlagSet(type, ts.TypeFlags.StringLike), ); if (strings.length) { @@ -803,7 +803,7 @@ export default util.createRule({ } const numbers = types.filter(type => - tsutils.isTypeFlagSet( + tools.isTypeFlagSet( type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ), @@ -819,7 +819,7 @@ export default util.createRule({ if ( types.some( type => - !tsutils.isTypeFlagSet( + !tools.isTypeFlagSet( type, ts.TypeFlags.Null | ts.TypeFlags.Undefined | @@ -851,7 +851,7 @@ export default util.createRule({ variantTypes.add('any'); } - if (types.some(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.Never))) { + if (types.some(type => tools.isTypeFlagSet(type, ts.TypeFlags.Never))) { variantTypes.add('never'); } diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index 76843d12942..4a5e1f7bf53 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -1,5 +1,5 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; -import { isTypeFlagSet, unionTypeParts } from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import { @@ -116,7 +116,7 @@ export default createRule({ const symbolName = discriminantType.getSymbol()?.escapedName; if (discriminantType.isUnion()) { - const unionTypes = unionTypeParts(discriminantType); + const unionTypes = tools.unionTypeParts(discriminantType); const caseTypes: Set = new Set(); for (const switchCase of node.cases) { if (switchCase.test == null) { @@ -144,7 +144,7 @@ export default createRule({ data: { missingBranches: missingBranchTypes .map(missingType => - isTypeFlagSet(missingType, ts.TypeFlags.ESSymbolLike) + tools.isTypeFlagSet(missingType, ts.TypeFlags.ESSymbolLike) ? `typeof ${missingType.getSymbol()?.escapedName as string}` : checker.typeToString(missingType), ) diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index 43971d621b4..1e44957ed81 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import * as tsutils from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import * as util from '../util'; @@ -162,7 +162,6 @@ export default util.createRule({ ], create(context, [{ ignoreStatic }]) { const services = util.getParserServices(context); - const checker = services.program.getTypeChecker(); const currentSourceFile = services.program.getSourceFile( context.getFilename(), ); @@ -282,7 +281,7 @@ function checkMethod( !thisArgIsVoid && !( ignoreStatic && - tsutils.hasModifier( + tools.hasModifier( getModifiers(valueDeclaration), ts.SyntaxKind.StaticKeyword, ) diff --git a/packages/type-utils/package.json b/packages/type-utils/package.json index 331cec87609..8042e8fdd3f 100644 --- a/packages/type-utils/package.json +++ b/packages/type-utils/package.json @@ -42,7 +42,7 @@ "@typescript-eslint/typescript-estree": "5.50.0", "@typescript-eslint/utils": "5.50.0", "debug": "^4.3.4", - "tsutils": "^3.21.0" + "ts-api-tools": "^0.0.15" }, "devDependencies": { "@typescript-eslint/parser": "5.50.0", diff --git a/packages/type-utils/src/containsAllTypesByName.ts b/packages/type-utils/src/containsAllTypesByName.ts index 07aa20dac04..715686fe3f7 100644 --- a/packages/type-utils/src/containsAllTypesByName.ts +++ b/packages/type-utils/src/containsAllTypesByName.ts @@ -1,4 +1,4 @@ -import { isTypeReference, isUnionOrIntersectionType } from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import { isTypeFlagSet } from './typeFlagUtils'; @@ -17,7 +17,7 @@ export function containsAllTypesByName( return !allowAny; } - if (isTypeReference(type)) { + if (tools.isTypeReference(type)) { type = type.target; } @@ -26,7 +26,7 @@ export function containsAllTypesByName( return true; } - if (isUnionOrIntersectionType(type)) { + if (tools.isUnionOrIntersectionType(type)) { return type.types.every(t => containsAllTypesByName(t, allowAny, allowedNames), ); diff --git a/packages/type-utils/src/getContextualType.ts b/packages/type-utils/src/getContextualType.ts index 07515628265..b19ceb936bd 100644 --- a/packages/type-utils/src/getContextualType.ts +++ b/packages/type-utils/src/getContextualType.ts @@ -1,14 +1,4 @@ -import { - isBinaryExpression, - isCallExpression, - isIdentifier, - isJsxExpression, - isNewExpression, - isParameterDeclaration, - isPropertyAssignment, - isPropertyDeclaration, - isVariableDeclaration, -} from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; /** @@ -25,23 +15,23 @@ export function getContextualType( return; } - if (isCallExpression(parent) || isNewExpression(parent)) { + if (ts.isCallExpression(parent) || ts.isNewExpression(parent)) { if (node === parent.expression) { // is the callee, so has no contextual type return; } } else if ( - isVariableDeclaration(parent) || - isPropertyDeclaration(parent) || - isParameterDeclaration(parent) + ts.isVariableDeclaration(parent) || + ts.isPropertyDeclaration(parent) || + tools.isParameterDeclaration(parent) ) { return parent.type ? checker.getTypeFromTypeNode(parent.type) : undefined; - } else if (isJsxExpression(parent)) { + } else if (ts.isJsxExpression(parent)) { return checker.getContextualType(parent); - } else if (isPropertyAssignment(parent) && isIdentifier(node)) { + } else if (ts.isPropertyAssignment(parent) && ts.isIdentifier(node)) { return checker.getContextualType(node); } else if ( - isBinaryExpression(parent) && + ts.isBinaryExpression(parent) && parent.operatorToken.kind === ts.SyntaxKind.EqualsToken && parent.right === node ) { diff --git a/packages/type-utils/src/isTypeReadonly.ts b/packages/type-utils/src/isTypeReadonly.ts index 7ba2b300089..649a38f40a2 100644 --- a/packages/type-utils/src/isTypeReadonly.ts +++ b/packages/type-utils/src/isTypeReadonly.ts @@ -1,13 +1,5 @@ import { ESLintUtils } from '@typescript-eslint/utils'; -import { - isConditionalType, - isIntersectionType, - isObjectType, - isPropertyReadonlyInType, - isSymbolFlagSet, - isUnionType, - unionTypeParts, -} from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import { getTypeOfPropertyOfType } from './propertyTypes'; @@ -136,7 +128,7 @@ function isTypeReadonlyObject( if ( property.valueDeclaration !== undefined && hasSymbol(property.valueDeclaration) && - isSymbolFlagSet( + tools.isSymbolFlagSet( property.valueDeclaration.symbol, ts.SymbolFlags.Method, ) @@ -152,13 +144,15 @@ function isTypeReadonlyObject( if ( lastDeclaration !== undefined && hasSymbol(lastDeclaration) && - isSymbolFlagSet(lastDeclaration.symbol, ts.SymbolFlags.Method) + tools.isSymbolFlagSet(lastDeclaration.symbol, ts.SymbolFlags.Method) ) { continue; } } - if (isPropertyReadonlyInType(type, property.getEscapedName(), checker)) { + if ( + tools.isPropertyReadonlyInType(type, property.getEscapedName(), checker) + ) { continue; } @@ -222,19 +216,21 @@ function isTypeReadonlyRecurser( ): Readonlyness.Readonly | Readonlyness.Mutable { seenTypes.add(type); - if (isUnionType(type)) { + if (tools.isUnionType(type)) { // all types in the union must be readonly - const result = unionTypeParts(type).every( - t => - seenTypes.has(t) || - isTypeReadonlyRecurser(checker, t, options, seenTypes) === - Readonlyness.Readonly, - ); + const result = tools + .unionTypeParts(type) + .every( + t => + seenTypes.has(t) || + isTypeReadonlyRecurser(checker, t, options, seenTypes) === + Readonlyness.Readonly, + ); const readonlyness = result ? Readonlyness.Readonly : Readonlyness.Mutable; return readonlyness; } - if (isIntersectionType(type)) { + if (tools.isIntersectionType(type)) { // Special case for handling arrays/tuples (as readonly arrays/tuples always have mutable methods). if ( type.types.some(t => checker.isArrayType(t) || checker.isTupleType(t)) @@ -260,7 +256,7 @@ function isTypeReadonlyRecurser( } } - if (isConditionalType(type)) { + if (tools.isConditionalType(type)) { const result = [type.root.node.trueType, type.root.node.falseType] .map(checker.getTypeFromTypeNode) .every( @@ -276,7 +272,7 @@ function isTypeReadonlyRecurser( // all non-object, non-intersection types are readonly. // this should only be primitive types - if (!isObjectType(type)) { + if (!tools.isObjectType(type)) { return Readonlyness.Readonly; } diff --git a/packages/type-utils/src/isUnsafeAssignment.ts b/packages/type-utils/src/isUnsafeAssignment.ts index f74220249ad..e14370da7a9 100644 --- a/packages/type-utils/src/isUnsafeAssignment.ts +++ b/packages/type-utils/src/isUnsafeAssignment.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import { isTypeReference } from 'tsutils'; +import * as tools from 'ts-api-tools'; import type * as ts from 'typescript'; import { isTypeAnyType, isTypeUnknownType } from './predicates'; @@ -32,7 +32,7 @@ export function isUnsafeAssignment( } } - if (isTypeReference(type) && isTypeReference(receiver)) { + if (tools.isTypeReference(type) && tools.isTypeReference(receiver)) { // TODO - figure out how to handle cases like this, // where the types are assignable, but not the same type /* diff --git a/packages/type-utils/src/predicates.ts b/packages/type-utils/src/predicates.ts index 72f59e4fc9d..281ad0a188a 100644 --- a/packages/type-utils/src/predicates.ts +++ b/packages/type-utils/src/predicates.ts @@ -1,5 +1,5 @@ import debug from 'debug'; -import { unionTypeParts } from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import { getTypeArguments } from './getTypeArguments'; @@ -39,7 +39,7 @@ export function isTypeArrayTypeOrUnionOfArrayTypes( type: ts.Type, checker: ts.TypeChecker, ): boolean { - for (const t of unionTypeParts(type)) { + for (const t of tools.unionTypeParts(type)) { if (!checker.isArrayType(t)) { return false; } diff --git a/packages/type-utils/src/typeFlagUtils.ts b/packages/type-utils/src/typeFlagUtils.ts index 134fdcf4ece..018c2f4de73 100644 --- a/packages/type-utils/src/typeFlagUtils.ts +++ b/packages/type-utils/src/typeFlagUtils.ts @@ -1,4 +1,4 @@ -import { unionTypeParts } from 'tsutils'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; /** @@ -6,7 +6,7 @@ import * as ts from 'typescript'; */ export function getTypeFlags(type: ts.Type): ts.TypeFlags { let flags: ts.TypeFlags = 0; - for (const t of unionTypeParts(type)) { + for (const t of tools.unionTypeParts(type)) { flags |= t.flags; } return flags; diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json index 180c4f71b69..244bd5d806f 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -48,7 +48,7 @@ "globby": "^11.1.0", "is-glob": "^4.0.3", "semver": "^7.3.7", - "tsutils": "^3.21.0" + "ts-api-tools": "^0.0.15" }, "devDependencies": { "@babel/code-frame": "*", diff --git a/packages/typescript-estree/src/convert-comments.ts b/packages/typescript-estree/src/convert-comments.ts index d4dd9f124a7..0ffcd226bb0 100644 --- a/packages/typescript-estree/src/convert-comments.ts +++ b/packages/typescript-estree/src/convert-comments.ts @@ -1,4 +1,4 @@ -import { forEachComment } from 'tsutils/util/util'; +import * as tools from 'ts-api-tools'; import * as ts from 'typescript'; import { getLocFor } from './node-utils'; @@ -18,7 +18,7 @@ export function convertComments( ): TSESTree.Comment[] { const comments: TSESTree.Comment[] = []; - forEachComment( + tools.forEachComment( ast, (_, comment) => { const type = diff --git a/patches/tsutils+3.21.0.patch b/patches/tsutils+3.21.0.patch deleted file mode 100644 index 0b2e3ee1036..00000000000 --- a/patches/tsutils+3.21.0.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/tsutils/util/util.d.ts b/node_modules/tsutils/util/util.d.ts -index 97cedda..4a63900 100644 ---- a/node_modules/tsutils/util/util.d.ts -+++ b/node_modules/tsutils/util/util.d.ts -@@ -9,7 +9,7 @@ export declare function isJsDocKind(kind: ts.SyntaxKind): boolean; - export declare function isKeywordKind(kind: ts.SyntaxKind): boolean; - export declare function isThisParameter(parameter: ts.ParameterDeclaration): boolean; - export declare function getModifier(node: ts.Node, kind: ts.Modifier['kind']): ts.Modifier | undefined; --export declare function hasModifier(modifiers: ts.ModifiersArray | undefined, ...kinds: Array): boolean; -+export declare function hasModifier(modifiers: Iterable | undefined, ...kinds: Array): boolean; - export declare function isParameterProperty(node: ts.ParameterDeclaration): boolean; - export declare function hasAccessModifier(node: ts.ClassElement | ts.ParameterDeclaration): boolean; - export declare const isNodeFlagSet: (node: ts.Node, flag: ts.NodeFlags) => boolean; diff --git a/yarn.lock b/yarn.lock index d5b9b45aa34..ddc6cf42af7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13659,6 +13659,11 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== +ts-api-tools@^0.0.15: + version "0.0.15" + resolved "https://registry.yarnpkg.com/ts-api-tools/-/ts-api-tools-0.0.15.tgz#d16750e0fdf7816a9b91da6af9db5b5167bfca80" + integrity sha512-aNaUSL3j1IvX2xRahC86OHLLhtuEEKful+HfgZs1TcYr2ZcukrENRxDIP1mjXdMojnfr2VflHqsFaaTp1m/bLw== + ts-essentials@^2.0.3: version "2.0.12" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745"