From 649a699bdc69be2d62da1fff101009c3067122d2 Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Mon, 26 Apr 2021 14:29:34 +1000 Subject: [PATCH 01/15] chore(experimental-utils): moved types eslint-plugin util to experimental-utils package --- .../eslint-plugin/src/rules/await-thenable.ts | 5 +- .../src/rules/no-base-to-string.ts | 11 +++- .../src/rules/no-confusing-void-expression.ts | 3 +- .../src/rules/no-for-in-array.ts | 5 +- .../src/rules/no-throw-literal.ts | 5 +- .../no-unnecessary-boolean-literal-compare.ts | 3 +- .../src/rules/no-unnecessary-condition.ts | 56 +++++++++++-------- .../rules/no-unnecessary-type-assertion.ts | 22 +++++--- .../src/rules/no-unsafe-argument.ts | 13 +++-- .../src/rules/no-unsafe-assignment.ts | 33 ++++++----- .../eslint-plugin/src/rules/no-unsafe-call.ts | 10 ++-- .../src/rules/no-unsafe-member-access.ts | 9 +-- .../src/rules/no-unsafe-return.ts | 28 ++++++---- .../src/rules/no-unused-vars-experimental.ts | 9 ++- .../src/rules/prefer-includes.ts | 10 +--- .../src/rules/prefer-nullish-coalescing.ts | 5 +- .../src/rules/prefer-readonly.ts | 4 +- .../src/rules/prefer-reduce-type-parameter.ts | 3 +- .../src/rules/prefer-regexp-exec.ts | 6 +- .../rules/prefer-string-starts-ends-with.ts | 4 +- .../src/rules/promise-function-async.ts | 8 ++- .../src/rules/require-array-sort-compare.ts | 10 ++-- .../src/rules/restrict-plus-operands.ts | 9 ++- .../rules/restrict-template-expressions.ts | 16 ++++-- .../eslint-plugin/src/rules/return-await.ts | 3 +- .../src/rules/strict-boolean-expressions.ts | 17 ++++-- .../src/rules/switch-exhaustiveness-check.ts | 9 ++- packages/eslint-plugin/src/util/index.ts | 1 - .../src/eslint-utils/index.ts | 1 + .../src/eslint-utils}/types.ts | 2 +- .../typings/typescript.d.ts | 33 +++++++++++ 31 files changed, 226 insertions(+), 127 deletions(-) rename packages/{eslint-plugin/src/util => experimental-utils/src/eslint-utils}/types.ts (99%) create mode 100644 packages/experimental-utils/typings/typescript.d.ts diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 9858bad8ba2..97cdc093f6f 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,3 +1,4 @@ +import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -29,8 +30,8 @@ export default util.createRule({ const type = checker.getTypeAtLocation(originalNode.expression); if ( - !util.isTypeAnyType(type) && - !util.isTypeUnknownType(type) && + !ESLintUtils.isTypeAnyType(type) && + !ESLintUtils.isTypeUnknownType(type) && !tsutils.isThenableType(checker, originalNode.expression, type) ) { context.report({ 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 b1593c23d8b..ca1fb9af218 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; @@ -99,7 +100,9 @@ export default util.createRule({ return Usefulness.Always; } - if (ignoredTypeNames.includes(util.getTypeName(typeChecker, type))) { + if ( + ignoredTypeNames.includes(ESLintUtils.getTypeName(typeChecker, type)) + ) { return Usefulness.Always; } @@ -165,9 +168,11 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node.right), ); - if (util.getTypeName(typeChecker, leftType) === 'string') { + if (ESLintUtils.getTypeName(typeChecker, leftType) === 'string') { checkExpression(node.right, rightType); - } else if (util.getTypeName(typeChecker, rightType) === 'string') { + } else if ( + ESLintUtils.getTypeName(typeChecker, rightType) === 'string' + ) { checkExpression(node.left, leftType); } }, 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 a9b715350e9..c2d7e540764 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -85,7 +86,7 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(checker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; 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 f89d2ffd08d..3e17d7ed90d 100644 --- a/packages/eslint-plugin/src/rules/no-for-in-array.ts +++ b/packages/eslint-plugin/src/rules/no-for-in-array.ts @@ -1,3 +1,4 @@ +import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -25,13 +26,13 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation( + const type = ESLintUtils.getConstrainedTypeAtLocation( checker, originalNode.expression, ); if ( - util.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || + ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || (type.flags & ts.TypeFlags.StringLike) !== 0 ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index 92bf3b02a13..a2a427c6b1e 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -3,6 +3,7 @@ import * as util from '../util'; import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; export default util.createRule({ @@ -79,8 +80,8 @@ export default util.createRule({ } if ( - util.isTypeAnyType(type) || - util.isTypeUnknownType(type) || + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type) || isErrorLike(type) ) { return; 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 fe1fd24cc4f..953debe328e 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,7 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -159,7 +160,7 @@ export default util.createRule({ function deconstructComparison( node: TSESTree.BinaryExpression, ): BooleanComparison | undefined { - const comparisonType = util.getEqualsKind(node.operator); + const comparisonType = ESLintUtils.getEqualsKind(node.operator); if (!comparisonType) { return undefined; } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index aee4963a0c0..ff028e1b479 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -2,6 +2,7 @@ import { TSESTree, AST_NODE_TYPES, AST_TOKEN_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { @@ -13,17 +14,11 @@ import { isStrictCompilerOptionEnabled, } from 'tsutils'; import { - isTypeFlagSet, createRule, getParserServices, - getConstrainedTypeAtLocation, - isNullableType, nullThrows, NullThrowsReasons, isIdentifier, - isTypeAnyType, - isTypeUnknownType, - getTypeName, getTypeOfPropertyOfName, } from '../util'; @@ -37,7 +32,7 @@ const isPossiblyFalsy = (type: ts.Type): boolean => // PossiblyFalsy flag includes literal values, so exclude ones that // are definitely truthy .filter(t => !isTruthyLiteral(t)) - .some(type => isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); + .some(type => ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); const isPossiblyTruthy = (type: ts.Type): boolean => unionTypeParts(type).some(type => !isFalsyType(type)); @@ -45,7 +40,7 @@ const isPossiblyTruthy = (type: ts.Type): boolean => // Nullish utilities const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; const isNullishType = (type: ts.Type): boolean => - isTypeFlagSet(type, nullishFlag); + ESLintUtils.isTypeFlagSet(type, nullishFlag); const isPossiblyNullish = (type: ts.Type): boolean => unionTypeParts(type).some(isNullishType); @@ -169,7 +164,7 @@ export default createRule({ function getNodeType(node: TSESTree.Expression): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return getConstrainedTypeAtLocation(checker, tsNode); + return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); } function nodeIsArrayType(node: TSESTree.Expression): boolean { @@ -238,16 +233,16 @@ export default createRule({ if ( unionTypeParts(type).some( part => - isTypeAnyType(part) || - isTypeUnknownType(part) || - isTypeFlagSet(part, ts.TypeFlags.TypeParameter), + ESLintUtils.isTypeAnyType(part) || + ESLintUtils.isTypeUnknownType(part) || + ESLintUtils.isTypeFlagSet(part, ts.TypeFlags.TypeParameter), ) ) { return; } let messageId: MessageId | null = null; - if (isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyTruthy(type)) { messageId = !isUnaryNotArgument ? 'alwaysFalsy' : 'alwaysTruthy'; @@ -269,12 +264,15 @@ export default createRule({ } const type = getNodeType(node); // Conditional is always necessary if it involves `any` or `unknown` - if (isTypeAnyType(type) || isTypeUnknownType(type)) { + if ( + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type) + ) { return; } let messageId: MessageId | null = null; - if (isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyNullish(type)) { messageId = 'neverNullish'; @@ -335,7 +333,7 @@ export default createRule({ flag |= NULL | UNDEFINED; } - return isTypeFlagSet(type, flag); + return ESLintUtils.isTypeFlagSet(type, flag); }; if ( @@ -451,7 +449,12 @@ export default createRule({ return; } // Predicate is always necessary if it involves `any` or `unknown` - if (returnTypes.some(t => isTypeAnyType(t) || isTypeUnknownType(t))) { + if ( + returnTypes.some( + t => + ESLintUtils.isTypeAnyType(t) || ESLintUtils.isTypeUnknownType(t), + ) + ) { return; } if (!returnTypes.some(isPossiblyFalsy)) { @@ -510,10 +513,10 @@ export default createRule({ propertyType.value.toString(), ); if (propType) { - return isNullableType(propType, { allowUndefined: true }); + return ESLintUtils.isNullableType(propType, { allowUndefined: true }); } } - const typeName = getTypeName(checker, propertyType); + const typeName = ESLintUtils.getTypeName(checker, propertyType); return !!( (typeName === 'string' && checker.getIndexInfoOfType(objType, ts.IndexKind.String)) || @@ -546,10 +549,14 @@ export default createRule({ type, property.name, ); - return propType && isNullableType(propType, { allowUndefined: true }); + return ( + propType && + ESLintUtils.isNullableType(propType, { allowUndefined: true }) + ); }); return ( - !isOwnNullable && isNullableType(prevType, { allowUndefined: true }) + !isOwnNullable && + ESLintUtils.isNullableType(prevType, { allowUndefined: true }) ); } return false; @@ -564,9 +571,10 @@ export default createRule({ ? !isNullableOriginFromPrev(node) : true; return ( - isTypeAnyType(type) || - isTypeUnknownType(type) || - (isNullableType(type, { allowUndefined: true }) && isOwnNullable) + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type) || + (ESLintUtils.isNullableType(type, { allowUndefined: true }) && + isOwnNullable) ); } 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 d16f494fc4a..cffad83f637 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { isObjectType, @@ -93,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: ts.Expression): boolean { - const declaration = util.getDeclaration(checker, node); + const declaration = ESLintUtils.getDeclaration(checker, node); if (!declaration) { // don't know what the declaration is for some reason, so just assume the worst return true; @@ -112,7 +113,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(checker, node); + const type = ESLintUtils.getConstrainedTypeAtLocation(checker, 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 @@ -160,12 +161,12 @@ export default util.createRule({ const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation( + const type = ESLintUtils.getConstrainedTypeAtLocation( checker, originalNode.expression, ); - if (!util.isNullableType(type)) { + if (!ESLintUtils.isNullableType(type)) { if (isPossiblyUsedBeforeAssigned(originalNode.expression)) { return; } @@ -184,24 +185,27 @@ 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 = ESLintUtils.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 = ESLintUtils.isTypeFlagSet( type, ts.TypeFlags.Undefined, ); - const typeIncludesNull = util.isTypeFlagSet( + const typeIncludesNull = ESLintUtils.isTypeFlagSet( type, ts.TypeFlags.Null, ); - const contextualTypeIncludesUndefined = util.isTypeFlagSet( + const contextualTypeIncludesUndefined = ESLintUtils.isTypeFlagSet( contextualType, ts.TypeFlags.Undefined, ); - const contextualTypeIncludesNull = util.isTypeFlagSet( + const contextualTypeIncludesNull = ESLintUtils.isTypeFlagSet( contextualType, ts.TypeFlags.Null, ); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts index 160519e2768..c4eb3e922e1 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts @@ -1,6 +1,7 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -168,7 +169,7 @@ export default util.createRule<[], MessageIds>({ // ignore any-typed calls as these are caught by no-unsafe-call if ( - util.isTypeAnyType( + ESLintUtils.isTypeAnyType( checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(node.callee)), ) ) { @@ -191,13 +192,15 @@ export default util.createRule<[], MessageIds>({ esTreeNodeToTSNodeMap.get(argument.argument), ); - if (util.isTypeAnyType(spreadArgType)) { + if (ESLintUtils.isTypeAnyType(spreadArgType)) { // foo(...any) context.report({ node: argument, messageId: 'unsafeSpread', }); - } else if (util.isTypeAnyArrayType(spreadArgType, checker)) { + } else if ( + ESLintUtils.isTypeAnyArrayType(spreadArgType, checker) + ) { // foo(...any[]) // TODO - we could break down the spread and compare the array type against each argument @@ -216,7 +219,7 @@ export default util.createRule<[], MessageIds>({ if (parameterType == null) { continue; } - const result = util.isUnsafeAssignment( + const result = ESLintUtils.isUnsafeAssignment( tupleType, parameterType, checker, @@ -254,7 +257,7 @@ export default util.createRule<[], MessageIds>({ const argumentType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(argument), ); - const result = util.isUnsafeAssignment( + const result = ESLintUtils.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 ac815208544..3e980e13699 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -74,7 +75,7 @@ export default util.createRule({ ): boolean { // any array // const [x] = ([] as any[]); - if (util.isTypeAnyArrayType(senderType, checker)) { + if (ESLintUtils.isTypeAnyArrayType(senderType, checker)) { context.report({ node: receiverNode, messageId: 'unsafeArrayPattern', @@ -86,7 +87,7 @@ export default util.createRule({ return true; } - const tupleElements = util.getTypeArguments(senderType, checker); + const tupleElements = ESLintUtils.getTypeArguments(senderType, checker); // tuple with any // const [x] = [1 as any]; @@ -112,7 +113,7 @@ export default util.createRule({ } // check for the any type first so we can handle [[[x]]] = [any] - if (util.isTypeAnyType(senderType)) { + if (ESLintUtils.isTypeAnyType(senderType)) { context.report({ node: receiverElement, messageId: 'unsafeArrayPatternFromTuple', @@ -203,7 +204,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 (ESLintUtils.isTypeAnyType(senderType)) { context.report({ node: receiverProperty.value, messageId: 'unsafeArrayPatternFromTuple', @@ -241,16 +242,18 @@ export default util.createRule({ const receiverTsNode = esTreeNodeToTSNodeMap.get(receiverNode); const receiverType = comparisonType === ComparisonType.Contextual - ? util.getContextualType(checker, receiverTsNode as ts.Expression) ?? - checker.getTypeAtLocation(receiverTsNode) + ? ESLintUtils.getContextualType( + checker, + receiverTsNode as ts.Expression, + ) ?? checker.getTypeAtLocation(receiverTsNode) : checker.getTypeAtLocation(receiverTsNode); const senderType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(senderNode), ); - if (util.isTypeAnyType(senderType)) { + if (ESLintUtils.isTypeAnyType(senderType)) { // handle cases when we assign any ==> unknown. - if (util.isTypeUnknownType(receiverType)) { + if (ESLintUtils.isTypeUnknownType(receiverType)) { return false; } @@ -261,8 +264,8 @@ export default util.createRule({ const thisExpression = getThisExpression(senderNode); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -283,7 +286,11 @@ export default util.createRule({ return false; } - const result = util.isUnsafeAssignment(senderType, receiverType, checker); + const result = ESLintUtils.isUnsafeAssignment( + senderType, + receiverType, + checker, + ); if (!result) { return false; } @@ -374,8 +381,8 @@ export default util.createRule({ const resetNode = esTreeNodeToTSNodeMap.get(node.argument); const restType = checker.getTypeAtLocation(resetNode); if ( - util.isTypeAnyType(restType) || - util.isTypeAnyArrayType(restType, checker) + ESLintUtils.isTypeAnyType(restType) || + ESLintUtils.isTypeAnyArrayType(restType, checker) ) { context.report({ node: node, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-call.ts b/packages/eslint-plugin/src/rules/no-unsafe-call.ts index b08214d36c2..7a9bdf0fe39 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-call.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-call.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; import { getThisExpression } from '../util'; @@ -46,16 +46,16 @@ export default util.createRule<[], MessageIds>({ messageId: MessageIds, ): void { const tsNode = esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(checker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); - if (util.isTypeAnyType(type)) { + if (ESLintUtils.isTypeAnyType(type)) { if (!isNoImplicitThis) { // `this()` or `this.foo()` or `this.foo[bar]()` const thisExpression = getThisExpression(node); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), 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 13fd7bf0821..d97b5e7b16d 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,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -64,7 +65,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node.object); const type = checker.getTypeAtLocation(tsNode); - const state = util.isTypeAnyType(type) ? State.Unsafe : State.Safe; + const state = ESLintUtils.isTypeAnyType(type) ? State.Unsafe : State.Safe; stateCache.set(node, state); if (state === State.Unsafe) { @@ -79,8 +80,8 @@ export default util.createRule({ if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -123,7 +124,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(tsNode); - if (util.isTypeAnyType(type)) { + if (ESLintUtils.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 a818be4ef4e..40dab46ef99 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-return.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-return.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -67,14 +68,17 @@ export default util.createRule({ reportingNode: TSESTree.Node = returnNode, ): void { const tsNode = esTreeNodeToTSNodeMap.get(returnNode); - const anyType = util.isAnyOrAnyArrayTypeDiscriminated(tsNode, checker); + const anyType = ESLintUtils.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( + const returnNodeType = ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(returnNode), ); @@ -85,26 +89,26 @@ export default util.createRule({ // 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) - ? util.getContextualType(checker, functionTSNode) + ? ESLintUtils.getContextualType(checker, functionTSNode) : checker.getTypeAtLocation(functionTSNode); if (!functionType) { functionType = checker.getTypeAtLocation(functionTSNode); } - if (anyType !== util.AnyType.Safe) { + if (anyType !== ESLintUtils.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 === ESLintUtils.AnyType.Any && + ESLintUtils.isTypeUnknownType(functionReturnType) ) { return; } if ( - anyType === util.AnyType.AnyArray && - util.isTypeUnknownArrayType(functionReturnType, checker) + anyType === ESLintUtils.AnyType.AnyArray && + ESLintUtils.isTypeUnknownArrayType(functionReturnType, checker) ) { return; } @@ -117,8 +121,8 @@ export default util.createRule({ const thisExpression = getThisExpression(returnNode); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -133,7 +137,7 @@ export default util.createRule({ node: reportingNode, messageId, data: { - type: anyType === util.AnyType.Any ? 'any' : 'any[]', + type: anyType === ESLintUtils.AnyType.Any ? 'any' : 'any[]', }, }); } @@ -147,7 +151,7 @@ export default util.createRule({ return; } - const result = util.isUnsafeAssignment( + const result = ESLintUtils.isUnsafeAssignment( returnNodeType, functionReturnType, checker, diff --git a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts index 0aedd20cbb2..5a6114de5f3 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts @@ -1,6 +1,6 @@ /* eslint-disable no-fallthrough */ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -294,13 +294,16 @@ export default util.createRule({ return { 'Program:exit'(program: TSESTree.Program): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(program); - const sourceFile = util.getSourceFileOfNode(tsNode); + const sourceFile = ESLintUtils.getSourceFileOfNode(tsNode); const diagnostics = tsProgram.getSemanticDiagnostics(sourceFile); diagnostics.forEach(diag => { if (isUnusedDiagnostic(diag.code)) { if (diag.start !== undefined) { - const node = util.getTokenAtPosition(sourceFile, diag.start); + const node = ESLintUtils.getTokenAtPosition( + sourceFile, + diag.start, + ); const parent = node.parent; if (isIdentifier(node)) { handleIdentifier(node); diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index f49b5385a0c..73d2632e601 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -1,15 +1,11 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, parseRegExpLiteral } from 'regexpp'; import * as ts from 'typescript'; -import { - createRule, - getParserServices, - getStaticValue, - getConstrainedTypeAtLocation, -} from '../util'; +import { createRule, getParserServices, getStaticValue } from '../util'; export default createRule({ name: 'prefer-includes', @@ -201,7 +197,7 @@ export default createRule({ //check the argument type of test methods const argument = callNode.arguments[0]; const tsNode = services.esTreeNodeToTSNodeMap.get(argument); - const type = getConstrainedTypeAtLocation(types, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation(types, tsNode); const includesMethodDecl = type .getProperty('includes') diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index fa6c1bb4e21..6816e9030b2 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -3,6 +3,7 @@ import { AST_TOKEN_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -66,7 +67,9 @@ 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 = ESLintUtils.isNullableType(type, { + allowUndefined: true, + }); if (!isNullish) { return; } diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 27eb7dca97c..eb30ce0d23b 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -1,10 +1,10 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; -import { typeIsOrHasBaseType } from '../util'; import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; type MessageIds = 'preferReadonly'; @@ -322,7 +322,7 @@ class ClassScope { const modifierType = this.checker.getTypeAtLocation(node.expression); if ( !modifierType.getSymbol() || - !typeIsOrHasBaseType(modifierType, this.classType) + !ESLintUtils.typeIsOrHasBaseType(modifierType, this.classType) ) { return; } 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 3b1af79ac6e..fa883a2e8bd 100644 --- a/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts +++ b/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts @@ -1,6 +1,7 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -67,7 +68,7 @@ export default util.createRule({ // Get the symbol of the `reduce` method. const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = util.getConstrainedTypeAtLocation( + const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( checker, tsNode, ); diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index d78c4496164..7e17093fe7e 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -1,12 +1,12 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { createRule, getParserServices, getStaticValue, - getTypeName, getWrappingFixer, } from '../util'; @@ -44,7 +44,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return getTypeName(typeChecker, objectType) === 'string'; + return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; } /** @@ -55,7 +55,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return getTypeName(typeChecker, objectType) === 'RegExp'; + return ESLintUtils.getTypeName(typeChecker, objectType) === 'RegExp'; } return { diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index f4697b7c01d..986f7279b45 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, RegExpParser } from 'regexpp'; import { @@ -9,7 +10,6 @@ import { getParserServices, getPropertyName, getStaticValue, - getTypeName, isNotClosingParenToken, nullThrows, NullThrowsReasons, @@ -53,7 +53,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( service.esTreeNodeToTSNodeMap.get(node), ); - return getTypeName(typeChecker, objectType) === 'string'; + return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; } /** diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 68b1d42567c..d96d4b05008 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -110,7 +111,7 @@ export default util.createRule({ const returnType = checker.getReturnTypeOfSignature(signatures[0]); if ( - !util.containsAllTypesByName( + !ESLintUtils.containsAllTypesByName( returnType, allowAny!, allAllowedPromiseNames, @@ -136,7 +137,10 @@ export default util.createRule({ } if ( - util.isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown) + ESLintUtils.isTypeFlagSet( + returnType, + ts.TypeFlags.Any | ts.TypeFlags.Unknown, + ) ) { // Report without auto fixer because the return type is unknown return context.report({ 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 6e0c49f31a8..0fa4fae7e12 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export type Options = [ @@ -55,7 +55,7 @@ export default util.createRule({ if (checker.isArrayType(type) || checker.isTupleType(type)) { const typeArgs = checker.getTypeArguments(type); return typeArgs.every( - arg => util.getTypeName(checker, arg) === 'string', + arg => ESLintUtils.getTypeName(checker, arg) === 'string', ); } return false; @@ -66,7 +66,7 @@ export default util.createRule({ callee: TSESTree.MemberExpression, ): void { const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = util.getConstrainedTypeAtLocation( + const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( checker, tsNode, ); @@ -75,7 +75,9 @@ export default util.createRule({ return; } - if (util.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) { + if ( + ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker) + ) { context.report({ node: callee.parent!, messageId: 'requireCompare' }); } }, diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index 0f3b07e9fb2..fe40dd81068 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -59,7 +59,7 @@ export default util.createRule({ } if ( type.isStringLiteral() || - util.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) + ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) ) { return 'string'; } @@ -96,7 +96,10 @@ export default util.createRule({ */ function getNodeType(node: TSESTree.Expression): BaseLiteral { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation( + typeChecker, + tsNode, + ); return getBaseTypeOfLiteralType(type); } diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index a4756266ffc..e969d559219 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -51,13 +52,13 @@ export default util.createRule({ const typeChecker = service.program.getTypeChecker(); function isUnderlyingTypePrimitive(type: ts.Type): boolean { - if (util.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { + if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { return true; } if ( options.allowNumber && - util.isTypeFlagSet( + ESLintUtils.isTypeFlagSet( type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ) @@ -67,18 +68,21 @@ export default util.createRule({ if ( options.allowBoolean && - util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) + ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) ) { return true; } - if (options.allowAny && util.isTypeAnyType(type)) { + if (options.allowAny && ESLintUtils.isTypeAnyType(type)) { return true; } if ( options.allowNullish && - util.isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined) + ESLintUtils.isTypeFlagSet( + type, + ts.TypeFlags.Null | ts.TypeFlags.Undefined, + ) ) { return true; } @@ -94,7 +98,7 @@ export default util.createRule({ } for (const expression of node.expressions) { - const expressionType = util.getConstrainedTypeAtLocation( + const expressionType = ESLintUtils.getConstrainedTypeAtLocation( typeChecker, service.esTreeNodeToTSNodeMap.get(expression), ); diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index 85a2eebe1f5..ad7a7ba8a15 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -172,7 +173,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) + ESLintUtils.isTypeAnyType(type) || ESLintUtils.isTypeUnknownType(type) ); const fix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix | null => removeAwait(fixer, node); diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 87796f9f427..55d3f89d647 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, ParserServices, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -225,7 +226,10 @@ export default util.createRule({ } const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation( + typeChecker, + tsNode, + ); const types = inspectVariantTypes(tsutils.unionTypeParts(type)); const is = (...wantedTypes: readonly VariantType[]): boolean => @@ -790,7 +794,9 @@ export default util.createRule({ if ( types.some( - type => util.isTypeAnyType(type) || util.isTypeUnknownType(type), + type => + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type), ) ) { variantTypes.add('any'); @@ -826,9 +832,12 @@ function isArrayLengthExpression( return false; } const objectTsNode = parserServices.esTreeNodeToTSNodeMap.get(node.object); - const objectType = util.getConstrainedTypeAtLocation( + const objectType = ESLintUtils.getConstrainedTypeAtLocation( typeChecker, objectTsNode, ); - return util.isTypeArrayTypeOrUnionOfArrayTypes(objectType, typeChecker); + return ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes( + objectType, + typeChecker, + ); } diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index 8881473da05..cd86d2ced8a 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -1,8 +1,11 @@ -import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + TSESLint, + TSESTree, + ESLintUtils, +} from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { createRule, - getConstrainedTypeAtLocation, getParserServices, isClosingBraceToken, isOpeningBraceToken, @@ -37,7 +40,7 @@ export default createRule({ function getNodeType(node: TSESTree.Node): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return getConstrainedTypeAtLocation(checker, tsNode); + return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); } function fixSwitch( diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 79e142b15fd..951f1dadd15 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -12,7 +12,6 @@ export * from './nullThrows'; export * from './objectIterators'; export * from './propertyTypes'; export * from './requiresQuoting'; -export * from './types'; // this is done for convenience - saves migrating all of the old rules const { diff --git a/packages/experimental-utils/src/eslint-utils/index.ts b/packages/experimental-utils/src/eslint-utils/index.ts index bbbe8df2709..2381db1d373 100644 --- a/packages/experimental-utils/src/eslint-utils/index.ts +++ b/packages/experimental-utils/src/eslint-utils/index.ts @@ -5,3 +5,4 @@ export * from './InferTypesFromRule'; export * from './RuleCreator'; export * from './RuleTester'; export * from './deepMerge'; +export * from './types'; diff --git a/packages/eslint-plugin/src/util/types.ts b/packages/experimental-utils/src/eslint-utils/types.ts similarity index 99% rename from packages/eslint-plugin/src/util/types.ts rename to packages/experimental-utils/src/eslint-utils/types.ts index 920ce66de02..67e279e200b 100644 --- a/packages/eslint-plugin/src/util/types.ts +++ b/packages/experimental-utils/src/eslint-utils/types.ts @@ -15,7 +15,7 @@ import { } from 'tsutils'; import * as ts from 'typescript'; -const log = debug('typescript-eslint:eslint-plugin:utils:types'); +const log = debug('typescript-eslint:experimental-utils:eslint-utils:types'); /** * Checks if the given type is either an array type, diff --git a/packages/experimental-utils/typings/typescript.d.ts b/packages/experimental-utils/typings/typescript.d.ts new file mode 100644 index 00000000000..73304155ee7 --- /dev/null +++ b/packages/experimental-utils/typings/typescript.d.ts @@ -0,0 +1,33 @@ +import 'typescript'; + +declare module 'typescript' { + interface TypeChecker { + // internal TS APIs + + /** + * @returns `true` if the given type is an array type: + * - `Array` + * - `ReadonlyArray` + * - `foo[]` + * - `readonly foo[]` + */ + isArrayType(type: Type): type is TypeReference; + /** + * @returns `true` if the given type is a tuple type: + * - `[foo]` + * - `readonly [foo]` + */ + isTupleType(type: Type): type is TupleTypeReference; + /** + * Return the type of the given property in the given type, or undefined if no such property exists + */ + getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; + } + + interface Type { + /** + * If the type is `any`, and this is set to "error", then TS was unable to resolve the type + */ + intrinsicName?: string; + } +} From 01e026a28b529d79b2cb6c19084fec72c6eb20a7 Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Wed, 19 May 2021 15:26:56 +1000 Subject: [PATCH 02/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- packages/eslint-plugin/src/util/index.ts | 1 + .../tests/util/isUnsafeAssignment.test.ts | 55 +++++++++++++------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 951f1dadd15..d2713b46167 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -12,6 +12,7 @@ export * from './nullThrows'; export * from './objectIterators'; export * from './propertyTypes'; export * from './requiresQuoting'; +export * from '@typescript-eslint/experimental-utils/dist/eslint-utils/types'; // this is done for convenience - saves migrating all of the old rules const { diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts index efe1fe9d1ba..60a027328c5 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts @@ -1,9 +1,8 @@ import * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'path'; import { getFixturesRootDir } from '../RuleTester'; -import { isUnsafeAssignment } from '../../src/util/types'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -34,7 +33,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, @@ -52,7 +51,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'any', 'string', @@ -65,7 +64,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Set', 'Set', @@ -78,7 +77,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Map', 'Map', @@ -91,7 +90,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Set', 'Set', @@ -104,7 +103,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Set>>', 'Set>>', @@ -118,13 +117,17 @@ describe('isUnsafeAssignment', () => { 'const test: string = "";', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any to a any', () => { const { sender, receiver, checker } = getTypes('const test: any = "";'); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any', () => { @@ -132,7 +135,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (multiple generics)', () => { @@ -140,7 +145,9 @@ describe('isUnsafeAssignment', () => { 'const test: Map = new Map();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any[] in a generic position to a non-any[]', () => { @@ -148,7 +155,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (nested)', () => { @@ -156,7 +165,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a any (nested)', () => { @@ -164,7 +175,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('any to a unknown', () => { @@ -172,7 +185,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown = [] as any;', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('any[] in a generic position to a unknown[]', () => { @@ -180,7 +195,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown[] = [] as any[]', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('any in a generic position to a unknown (nested)', () => { @@ -188,7 +205,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); }); }); From 95fd90c3f2ea2904a658b106e6ef9413e250df5e Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Tue, 1 Jun 2021 18:24:29 +1000 Subject: [PATCH 03/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- .../eslint-plugin/src/rules/await-thenable.ts | 5 +- .../src/rules/no-base-to-string.ts | 11 +--- .../src/rules/no-confusing-void-expression.ts | 3 +- .../src/rules/no-for-in-array.ts | 5 +- .../src/rules/no-throw-literal.ts | 5 +- .../no-unnecessary-boolean-literal-compare.ts | 3 +- .../src/rules/no-unnecessary-condition.ts | 56 ++++++++----------- .../rules/no-unnecessary-type-assertion.ts | 22 +++----- .../src/rules/no-unsafe-argument.ts | 13 ++--- .../src/rules/no-unsafe-assignment.ts | 33 +++++------ .../eslint-plugin/src/rules/no-unsafe-call.ts | 10 ++-- .../src/rules/no-unsafe-member-access.ts | 9 ++- .../src/rules/no-unsafe-return.ts | 28 ++++------ .../src/rules/no-unused-vars-experimental.ts | 9 +-- .../src/rules/prefer-includes.ts | 10 +++- .../src/rules/prefer-nullish-coalescing.ts | 5 +- .../src/rules/prefer-readonly.ts | 4 +- .../src/rules/prefer-reduce-type-parameter.ts | 3 +- .../src/rules/prefer-regexp-exec.ts | 6 +- .../rules/prefer-string-starts-ends-with.ts | 4 +- .../src/rules/promise-function-async.ts | 8 +-- .../src/rules/require-array-sort-compare.ts | 10 ++-- .../src/rules/restrict-plus-operands.ts | 9 +-- .../rules/restrict-template-expressions.ts | 16 ++---- .../eslint-plugin/src/rules/return-await.ts | 3 +- .../src/rules/strict-boolean-expressions.ts | 17 ++---- .../src/rules/switch-exhaustiveness-check.ts | 9 +-- 27 files changed, 125 insertions(+), 191 deletions(-) diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 97cdc093f6f..9858bad8ba2 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,4 +1,3 @@ -import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -30,8 +29,8 @@ export default util.createRule({ const type = checker.getTypeAtLocation(originalNode.expression); if ( - !ESLintUtils.isTypeAnyType(type) && - !ESLintUtils.isTypeUnknownType(type) && + !util.isTypeAnyType(type) && + !util.isTypeUnknownType(type) && !tsutils.isThenableType(checker, originalNode.expression, type) ) { context.report({ 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 ca1fb9af218..b1593c23d8b 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; @@ -100,9 +99,7 @@ export default util.createRule({ return Usefulness.Always; } - if ( - ignoredTypeNames.includes(ESLintUtils.getTypeName(typeChecker, type)) - ) { + if (ignoredTypeNames.includes(util.getTypeName(typeChecker, type))) { return Usefulness.Always; } @@ -168,11 +165,9 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node.right), ); - if (ESLintUtils.getTypeName(typeChecker, leftType) === 'string') { + if (util.getTypeName(typeChecker, leftType) === 'string') { checkExpression(node.right, rightType); - } else if ( - ESLintUtils.getTypeName(typeChecker, rightType) === 'string' - ) { + } else if (util.getTypeName(typeChecker, rightType) === 'string') { checkExpression(node.left, leftType); } }, 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 c2d7e540764..a9b715350e9 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -86,7 +85,7 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + const type = util.getConstrainedTypeAtLocation(checker, tsNode); if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; 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 3e17d7ed90d..f89d2ffd08d 100644 --- a/packages/eslint-plugin/src/rules/no-for-in-array.ts +++ b/packages/eslint-plugin/src/rules/no-for-in-array.ts @@ -1,4 +1,3 @@ -import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -26,13 +25,13 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( + const type = util.getConstrainedTypeAtLocation( checker, originalNode.expression, ); if ( - ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || + util.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || (type.flags & ts.TypeFlags.StringLike) !== 0 ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index a2a427c6b1e..92bf3b02a13 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -3,7 +3,6 @@ import * as util from '../util'; import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; export default util.createRule({ @@ -80,8 +79,8 @@ export default util.createRule({ } if ( - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type) || + util.isTypeAnyType(type) || + util.isTypeUnknownType(type) || isErrorLike(type) ) { return; 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 953debe328e..fe1fd24cc4f 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,7 +1,6 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -160,7 +159,7 @@ export default util.createRule({ function deconstructComparison( node: TSESTree.BinaryExpression, ): BooleanComparison | undefined { - const comparisonType = ESLintUtils.getEqualsKind(node.operator); + const comparisonType = util.getEqualsKind(node.operator); if (!comparisonType) { return undefined; } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 2064e7eb7de..f5ca89e88d6 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -2,7 +2,6 @@ import { TSESTree, AST_NODE_TYPES, AST_TOKEN_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { @@ -14,11 +13,17 @@ import { isStrictCompilerOptionEnabled, } from 'tsutils'; import { + isTypeFlagSet, createRule, getParserServices, + getConstrainedTypeAtLocation, + isNullableType, nullThrows, NullThrowsReasons, isIdentifier, + isTypeAnyType, + isTypeUnknownType, + getTypeName, getTypeOfPropertyOfName, } from '../util'; @@ -32,7 +37,7 @@ const isPossiblyFalsy = (type: ts.Type): boolean => // PossiblyFalsy flag includes literal values, so exclude ones that // are definitely truthy .filter(t => !isTruthyLiteral(t)) - .some(type => ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); + .some(type => isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); const isPossiblyTruthy = (type: ts.Type): boolean => unionTypeParts(type).some(type => !isFalsyType(type)); @@ -40,7 +45,7 @@ const isPossiblyTruthy = (type: ts.Type): boolean => // Nullish utilities const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; const isNullishType = (type: ts.Type): boolean => - ESLintUtils.isTypeFlagSet(type, nullishFlag); + isTypeFlagSet(type, nullishFlag); const isPossiblyNullish = (type: ts.Type): boolean => unionTypeParts(type).some(isNullishType); @@ -164,7 +169,7 @@ export default createRule({ function getNodeType(node: TSESTree.Node): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + return getConstrainedTypeAtLocation(checker, tsNode); } function nodeIsArrayType(node: TSESTree.Expression): boolean { @@ -233,16 +238,16 @@ export default createRule({ if ( unionTypeParts(type).some( part => - ESLintUtils.isTypeAnyType(part) || - ESLintUtils.isTypeUnknownType(part) || - ESLintUtils.isTypeFlagSet(part, ts.TypeFlags.TypeParameter), + isTypeAnyType(part) || + isTypeUnknownType(part) || + isTypeFlagSet(part, ts.TypeFlags.TypeParameter), ) ) { return; } let messageId: MessageId | null = null; - if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyTruthy(type)) { messageId = !isUnaryNotArgument ? 'alwaysFalsy' : 'alwaysTruthy'; @@ -264,15 +269,12 @@ export default createRule({ } const type = getNodeType(node); // Conditional is always necessary if it involves `any` or `unknown` - if ( - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type) - ) { + if (isTypeAnyType(type) || isTypeUnknownType(type)) { return; } let messageId: MessageId | null = null; - if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyNullish(type)) { messageId = 'neverNullish'; @@ -333,7 +335,7 @@ export default createRule({ flag |= NULL | UNDEFINED; } - return ESLintUtils.isTypeFlagSet(type, flag); + return isTypeFlagSet(type, flag); }; if ( @@ -449,12 +451,7 @@ export default createRule({ return; } // Predicate is always necessary if it involves `any` or `unknown` - if ( - returnTypes.some( - t => - ESLintUtils.isTypeAnyType(t) || ESLintUtils.isTypeUnknownType(t), - ) - ) { + if (returnTypes.some(t => isTypeAnyType(t) || isTypeUnknownType(t))) { return; } if (!returnTypes.some(isPossiblyFalsy)) { @@ -513,10 +510,10 @@ export default createRule({ propertyType.value.toString(), ); if (propType) { - return ESLintUtils.isNullableType(propType, { allowUndefined: true }); + return isNullableType(propType, { allowUndefined: true }); } } - const typeName = ESLintUtils.getTypeName(checker, propertyType); + const typeName = getTypeName(checker, propertyType); return !!( (typeName === 'string' && checker.getIndexInfoOfType(objType, ts.IndexKind.String)) || @@ -549,14 +546,10 @@ export default createRule({ type, property.name, ); - return ( - propType && - ESLintUtils.isNullableType(propType, { allowUndefined: true }) - ); + return propType && isNullableType(propType, { allowUndefined: true }); }); return ( - !isOwnNullable && - ESLintUtils.isNullableType(prevType, { allowUndefined: true }) + !isOwnNullable && isNullableType(prevType, { allowUndefined: true }) ); } return false; @@ -571,10 +564,9 @@ export default createRule({ ? !isNullableOriginFromPrev(node) : true; return ( - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type) || - (ESLintUtils.isNullableType(type, { allowUndefined: true }) && - isOwnNullable) + isTypeAnyType(type) || + isTypeUnknownType(type) || + (isNullableType(type, { allowUndefined: true }) && isOwnNullable) ); } 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 cffad83f637..d16f494fc4a 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { isObjectType, @@ -94,7 +93,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: ts.Expression): boolean { - const declaration = ESLintUtils.getDeclaration(checker, node); + const declaration = util.getDeclaration(checker, node); if (!declaration) { // don't know what the declaration is for some reason, so just assume the worst return true; @@ -113,7 +112,7 @@ export default util.createRule({ ) { // check if the defined variable type has changed since assignment const declarationType = checker.getTypeFromTypeNode(declaration.type); - const type = ESLintUtils.getConstrainedTypeAtLocation(checker, node); + const type = util.getConstrainedTypeAtLocation(checker, 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 @@ -161,12 +160,12 @@ export default util.createRule({ const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( + const type = util.getConstrainedTypeAtLocation( checker, originalNode.expression, ); - if (!ESLintUtils.isNullableType(type)) { + if (!util.isNullableType(type)) { if (isPossiblyUsedBeforeAssigned(originalNode.expression)) { return; } @@ -185,27 +184,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 = ESLintUtils.getContextualType( - checker, - originalNode, - ); + const contextualType = util.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 = ESLintUtils.isTypeFlagSet( + const typeIncludesUndefined = util.isTypeFlagSet( type, ts.TypeFlags.Undefined, ); - const typeIncludesNull = ESLintUtils.isTypeFlagSet( + const typeIncludesNull = util.isTypeFlagSet( type, ts.TypeFlags.Null, ); - const contextualTypeIncludesUndefined = ESLintUtils.isTypeFlagSet( + const contextualTypeIncludesUndefined = util.isTypeFlagSet( contextualType, ts.TypeFlags.Undefined, ); - const contextualTypeIncludesNull = ESLintUtils.isTypeFlagSet( + const contextualTypeIncludesNull = util.isTypeFlagSet( contextualType, ts.TypeFlags.Null, ); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts index c4eb3e922e1..160519e2768 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts @@ -1,7 +1,6 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -169,7 +168,7 @@ export default util.createRule<[], MessageIds>({ // ignore any-typed calls as these are caught by no-unsafe-call if ( - ESLintUtils.isTypeAnyType( + util.isTypeAnyType( checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(node.callee)), ) ) { @@ -192,15 +191,13 @@ export default util.createRule<[], MessageIds>({ esTreeNodeToTSNodeMap.get(argument.argument), ); - if (ESLintUtils.isTypeAnyType(spreadArgType)) { + if (util.isTypeAnyType(spreadArgType)) { // foo(...any) context.report({ node: argument, messageId: 'unsafeSpread', }); - } else if ( - ESLintUtils.isTypeAnyArrayType(spreadArgType, checker) - ) { + } else if (util.isTypeAnyArrayType(spreadArgType, checker)) { // foo(...any[]) // TODO - we could break down the spread and compare the array type against each argument @@ -219,7 +216,7 @@ export default util.createRule<[], MessageIds>({ if (parameterType == null) { continue; } - const result = ESLintUtils.isUnsafeAssignment( + const result = util.isUnsafeAssignment( tupleType, parameterType, checker, @@ -257,7 +254,7 @@ export default util.createRule<[], MessageIds>({ const argumentType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(argument), ); - const result = ESLintUtils.isUnsafeAssignment( + const result = util.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 3e980e13699..ac815208544 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -75,7 +74,7 @@ export default util.createRule({ ): boolean { // any array // const [x] = ([] as any[]); - if (ESLintUtils.isTypeAnyArrayType(senderType, checker)) { + if (util.isTypeAnyArrayType(senderType, checker)) { context.report({ node: receiverNode, messageId: 'unsafeArrayPattern', @@ -87,7 +86,7 @@ export default util.createRule({ return true; } - const tupleElements = ESLintUtils.getTypeArguments(senderType, checker); + const tupleElements = util.getTypeArguments(senderType, checker); // tuple with any // const [x] = [1 as any]; @@ -113,7 +112,7 @@ export default util.createRule({ } // check for the any type first so we can handle [[[x]]] = [any] - if (ESLintUtils.isTypeAnyType(senderType)) { + if (util.isTypeAnyType(senderType)) { context.report({ node: receiverElement, messageId: 'unsafeArrayPatternFromTuple', @@ -204,7 +203,7 @@ export default util.createRule({ } // check for the any type first so we can handle {x: {y: z}} = {x: any} - if (ESLintUtils.isTypeAnyType(senderType)) { + if (util.isTypeAnyType(senderType)) { context.report({ node: receiverProperty.value, messageId: 'unsafeArrayPatternFromTuple', @@ -242,18 +241,16 @@ export default util.createRule({ const receiverTsNode = esTreeNodeToTSNodeMap.get(receiverNode); const receiverType = comparisonType === ComparisonType.Contextual - ? ESLintUtils.getContextualType( - checker, - receiverTsNode as ts.Expression, - ) ?? checker.getTypeAtLocation(receiverTsNode) + ? util.getContextualType(checker, receiverTsNode as ts.Expression) ?? + checker.getTypeAtLocation(receiverTsNode) : checker.getTypeAtLocation(receiverTsNode); const senderType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(senderNode), ); - if (ESLintUtils.isTypeAnyType(senderType)) { + if (util.isTypeAnyType(senderType)) { // handle cases when we assign any ==> unknown. - if (ESLintUtils.isTypeUnknownType(receiverType)) { + if (util.isTypeUnknownType(receiverType)) { return false; } @@ -264,8 +261,8 @@ export default util.createRule({ const thisExpression = getThisExpression(senderNode); if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -286,11 +283,7 @@ export default util.createRule({ return false; } - const result = ESLintUtils.isUnsafeAssignment( - senderType, - receiverType, - checker, - ); + const result = util.isUnsafeAssignment(senderType, receiverType, checker); if (!result) { return false; } @@ -381,8 +374,8 @@ export default util.createRule({ const resetNode = esTreeNodeToTSNodeMap.get(node.argument); const restType = checker.getTypeAtLocation(resetNode); if ( - ESLintUtils.isTypeAnyType(restType) || - ESLintUtils.isTypeAnyArrayType(restType, checker) + util.isTypeAnyType(restType) || + util.isTypeAnyArrayType(restType, checker) ) { context.report({ node: node, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-call.ts b/packages/eslint-plugin/src/rules/no-unsafe-call.ts index 7a9bdf0fe39..b08214d36c2 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-call.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-call.ts @@ -1,4 +1,4 @@ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; import { getThisExpression } from '../util'; @@ -46,16 +46,16 @@ export default util.createRule<[], MessageIds>({ messageId: MessageIds, ): void { const tsNode = esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + const type = util.getConstrainedTypeAtLocation(checker, tsNode); - if (ESLintUtils.isTypeAnyType(type)) { + if (util.isTypeAnyType(type)) { if (!isNoImplicitThis) { // `this()` or `this.foo()` or `this.foo[bar]()` const thisExpression = getThisExpression(node); if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), 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 d97b5e7b16d..13fd7bf0821 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -65,7 +64,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node.object); const type = checker.getTypeAtLocation(tsNode); - const state = ESLintUtils.isTypeAnyType(type) ? State.Unsafe : State.Safe; + const state = util.isTypeAnyType(type) ? State.Unsafe : State.Safe; stateCache.set(node, state); if (state === State.Unsafe) { @@ -80,8 +79,8 @@ export default util.createRule({ if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -124,7 +123,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(tsNode); - if (ESLintUtils.isTypeAnyType(type)) { + if (util.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 40dab46ef99..a818be4ef4e 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-return.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-return.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -68,17 +67,14 @@ export default util.createRule({ reportingNode: TSESTree.Node = returnNode, ): void { const tsNode = esTreeNodeToTSNodeMap.get(returnNode); - const anyType = ESLintUtils.isAnyOrAnyArrayTypeDiscriminated( - tsNode, - checker, - ); + const anyType = util.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 = ESLintUtils.getConstrainedTypeAtLocation( + const returnNodeType = util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(returnNode), ); @@ -89,26 +85,26 @@ export default util.createRule({ // 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) - ? ESLintUtils.getContextualType(checker, functionTSNode) + ? util.getContextualType(checker, functionTSNode) : checker.getTypeAtLocation(functionTSNode); if (!functionType) { functionType = checker.getTypeAtLocation(functionTSNode); } - if (anyType !== ESLintUtils.AnyType.Safe) { + if (anyType !== util.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 === ESLintUtils.AnyType.Any && - ESLintUtils.isTypeUnknownType(functionReturnType) + anyType === util.AnyType.Any && + util.isTypeUnknownType(functionReturnType) ) { return; } if ( - anyType === ESLintUtils.AnyType.AnyArray && - ESLintUtils.isTypeUnknownArrayType(functionReturnType, checker) + anyType === util.AnyType.AnyArray && + util.isTypeUnknownArrayType(functionReturnType, checker) ) { return; } @@ -121,8 +117,8 @@ export default util.createRule({ const thisExpression = getThisExpression(returnNode); if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -137,7 +133,7 @@ export default util.createRule({ node: reportingNode, messageId, data: { - type: anyType === ESLintUtils.AnyType.Any ? 'any' : 'any[]', + type: anyType === util.AnyType.Any ? 'any' : 'any[]', }, }); } @@ -151,7 +147,7 @@ export default util.createRule({ return; } - const result = ESLintUtils.isUnsafeAssignment( + const result = util.isUnsafeAssignment( returnNodeType, functionReturnType, checker, diff --git a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts index 5a6114de5f3..0aedd20cbb2 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts @@ -1,6 +1,6 @@ /* eslint-disable no-fallthrough */ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -294,16 +294,13 @@ export default util.createRule({ return { 'Program:exit'(program: TSESTree.Program): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(program); - const sourceFile = ESLintUtils.getSourceFileOfNode(tsNode); + const sourceFile = util.getSourceFileOfNode(tsNode); const diagnostics = tsProgram.getSemanticDiagnostics(sourceFile); diagnostics.forEach(diag => { if (isUnusedDiagnostic(diag.code)) { if (diag.start !== undefined) { - const node = ESLintUtils.getTokenAtPosition( - sourceFile, - diag.start, - ); + const node = util.getTokenAtPosition(sourceFile, diag.start); const parent = node.parent; if (isIdentifier(node)) { handleIdentifier(node); diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index 73d2632e601..f49b5385a0c 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -1,11 +1,15 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, parseRegExpLiteral } from 'regexpp'; import * as ts from 'typescript'; -import { createRule, getParserServices, getStaticValue } from '../util'; +import { + createRule, + getParserServices, + getStaticValue, + getConstrainedTypeAtLocation, +} from '../util'; export default createRule({ name: 'prefer-includes', @@ -197,7 +201,7 @@ export default createRule({ //check the argument type of test methods const argument = callNode.arguments[0]; const tsNode = services.esTreeNodeToTSNodeMap.get(argument); - const type = ESLintUtils.getConstrainedTypeAtLocation(types, tsNode); + const type = getConstrainedTypeAtLocation(types, tsNode); const includesMethodDecl = type .getProperty('includes') diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index 6816e9030b2..fa6c1bb4e21 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -3,7 +3,6 @@ import { AST_TOKEN_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -67,9 +66,7 @@ export default util.createRule({ ): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(tsNode.left); - const isNullish = ESLintUtils.isNullableType(type, { - allowUndefined: true, - }); + const isNullish = util.isNullableType(type, { allowUndefined: true }); if (!isNullish) { return; } diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index eb30ce0d23b..27eb7dca97c 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -1,10 +1,10 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; +import { typeIsOrHasBaseType } from '../util'; import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; type MessageIds = 'preferReadonly'; @@ -322,7 +322,7 @@ class ClassScope { const modifierType = this.checker.getTypeAtLocation(node.expression); if ( !modifierType.getSymbol() || - !ESLintUtils.typeIsOrHasBaseType(modifierType, this.classType) + !typeIsOrHasBaseType(modifierType, this.classType) ) { return; } 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 fa883a2e8bd..3b1af79ac6e 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,6 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -68,7 +67,7 @@ export default util.createRule({ // Get the symbol of the `reduce` method. const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( + const calleeObjType = util.getConstrainedTypeAtLocation( checker, tsNode, ); diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index 90a2af78e32..636fe2b3825 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -1,12 +1,12 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { createRule, getParserServices, getStaticValue, + getTypeName, getWrappingFixer, } from '../util'; @@ -44,7 +44,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; + return getTypeName(typeChecker, objectType) === 'string'; } /** @@ -55,7 +55,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return ESLintUtils.getTypeName(typeChecker, objectType) === 'RegExp'; + return getTypeName(typeChecker, objectType) === 'RegExp'; } return { diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index 986f7279b45..f4697b7c01d 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, RegExpParser } from 'regexpp'; import { @@ -10,6 +9,7 @@ import { getParserServices, getPropertyName, getStaticValue, + getTypeName, isNotClosingParenToken, nullThrows, NullThrowsReasons, @@ -53,7 +53,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( service.esTreeNodeToTSNodeMap.get(node), ); - return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; + return getTypeName(typeChecker, objectType) === 'string'; } /** diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index d96d4b05008..68b1d42567c 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -111,7 +110,7 @@ export default util.createRule({ const returnType = checker.getReturnTypeOfSignature(signatures[0]); if ( - !ESLintUtils.containsAllTypesByName( + !util.containsAllTypesByName( returnType, allowAny!, allAllowedPromiseNames, @@ -137,10 +136,7 @@ export default util.createRule({ } if ( - ESLintUtils.isTypeFlagSet( - returnType, - ts.TypeFlags.Any | ts.TypeFlags.Unknown, - ) + util.isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown) ) { // Report without auto fixer because the return type is unknown return context.report({ 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 0fa4fae7e12..6e0c49f31a8 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -1,4 +1,4 @@ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export type Options = [ @@ -55,7 +55,7 @@ export default util.createRule({ if (checker.isArrayType(type) || checker.isTupleType(type)) { const typeArgs = checker.getTypeArguments(type); return typeArgs.every( - arg => ESLintUtils.getTypeName(checker, arg) === 'string', + arg => util.getTypeName(checker, arg) === 'string', ); } return false; @@ -66,7 +66,7 @@ export default util.createRule({ callee: TSESTree.MemberExpression, ): void { const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( + const calleeObjType = util.getConstrainedTypeAtLocation( checker, tsNode, ); @@ -75,9 +75,7 @@ export default util.createRule({ return; } - if ( - ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker) - ) { + if (util.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) { context.report({ node: callee.parent!, messageId: 'requireCompare' }); } }, diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index fe40dd81068..0f3b07e9fb2 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -1,4 +1,4 @@ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -59,7 +59,7 @@ export default util.createRule({ } if ( type.isStringLiteral() || - ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) + util.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) ) { return 'string'; } @@ -96,10 +96,7 @@ export default util.createRule({ */ function getNodeType(node: TSESTree.Expression): BaseLiteral { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( - typeChecker, - tsNode, - ); + const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); return getBaseTypeOfLiteralType(type); } diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index e969d559219..a4756266ffc 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -52,13 +51,13 @@ export default util.createRule({ const typeChecker = service.program.getTypeChecker(); function isUnderlyingTypePrimitive(type: ts.Type): boolean { - if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { + if (util.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { return true; } if ( options.allowNumber && - ESLintUtils.isTypeFlagSet( + util.isTypeFlagSet( type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ) @@ -68,21 +67,18 @@ export default util.createRule({ if ( options.allowBoolean && - ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) + util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) ) { return true; } - if (options.allowAny && ESLintUtils.isTypeAnyType(type)) { + if (options.allowAny && util.isTypeAnyType(type)) { return true; } if ( options.allowNullish && - ESLintUtils.isTypeFlagSet( - type, - ts.TypeFlags.Null | ts.TypeFlags.Undefined, - ) + util.isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined) ) { return true; } @@ -98,7 +94,7 @@ export default util.createRule({ } for (const expression of node.expressions) { - const expressionType = ESLintUtils.getConstrainedTypeAtLocation( + const expressionType = util.getConstrainedTypeAtLocation( typeChecker, service.esTreeNodeToTSNodeMap.get(expression), ); diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index ad7a7ba8a15..85a2eebe1f5 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -173,7 +172,7 @@ export default util.createRule({ if (isAwait && !isThenable) { // any/unknown could be thenable; do not auto-fix const useAutoFix = !( - ESLintUtils.isTypeAnyType(type) || ESLintUtils.isTypeUnknownType(type) + util.isTypeAnyType(type) || util.isTypeUnknownType(type) ); const fix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix | null => removeAwait(fixer, node); diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 55d3f89d647..87796f9f427 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, ParserServices, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -226,10 +225,7 @@ export default util.createRule({ } const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( - typeChecker, - tsNode, - ); + const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); const types = inspectVariantTypes(tsutils.unionTypeParts(type)); const is = (...wantedTypes: readonly VariantType[]): boolean => @@ -794,9 +790,7 @@ export default util.createRule({ if ( types.some( - type => - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type), + type => util.isTypeAnyType(type) || util.isTypeUnknownType(type), ) ) { variantTypes.add('any'); @@ -832,12 +826,9 @@ function isArrayLengthExpression( return false; } const objectTsNode = parserServices.esTreeNodeToTSNodeMap.get(node.object); - const objectType = ESLintUtils.getConstrainedTypeAtLocation( + const objectType = util.getConstrainedTypeAtLocation( typeChecker, objectTsNode, ); - return ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes( - objectType, - typeChecker, - ); + return util.isTypeArrayTypeOrUnionOfArrayTypes(objectType, typeChecker); } diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index cd86d2ced8a..8881473da05 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -1,11 +1,8 @@ -import { - TSESLint, - TSESTree, - ESLintUtils, -} from '@typescript-eslint/experimental-utils'; +import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { createRule, + getConstrainedTypeAtLocation, getParserServices, isClosingBraceToken, isOpeningBraceToken, @@ -40,7 +37,7 @@ export default createRule({ function getNodeType(node: TSESTree.Node): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + return getConstrainedTypeAtLocation(checker, tsNode); } function fixSwitch( From 2a4fd07182e9a096b6f5bf375a6225a8b26e1ac9 Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Tue, 1 Jun 2021 18:35:05 +1000 Subject: [PATCH 04/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- .../tests/util/isUnsafeAssignment.test.ts | 55 ++++++------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts index 60a027328c5..95780856bc3 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts @@ -1,8 +1,9 @@ import * as ts from 'typescript'; -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'path'; import { getFixturesRootDir } from '../RuleTester'; +import { isUnsafeAssignment } from '../../src/util'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -33,7 +34,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, @@ -51,7 +52,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + isUnsafeAssignment(sender, receiver, checker), checker, 'any', 'string', @@ -64,7 +65,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + isUnsafeAssignment(sender, receiver, checker), checker, 'Set', 'Set', @@ -77,7 +78,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + isUnsafeAssignment(sender, receiver, checker), checker, 'Map', 'Map', @@ -90,7 +91,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + isUnsafeAssignment(sender, receiver, checker), checker, 'Set', 'Set', @@ -103,7 +104,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + isUnsafeAssignment(sender, receiver, checker), checker, 'Set>>', 'Set>>', @@ -117,17 +118,13 @@ describe('isUnsafeAssignment', () => { 'const test: string = "";', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('non-any to a any', () => { const { sender, receiver, checker } = getTypes('const test: any = "";'); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('non-any in a generic position to a non-any', () => { @@ -135,9 +132,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('non-any in a generic position to a non-any (multiple generics)', () => { @@ -145,9 +140,7 @@ describe('isUnsafeAssignment', () => { 'const test: Map = new Map();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('non-any[] in a generic position to a non-any[]', () => { @@ -155,9 +148,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('non-any in a generic position to a non-any (nested)', () => { @@ -165,9 +156,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('non-any in a generic position to a any (nested)', () => { @@ -175,9 +164,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('any to a unknown', () => { @@ -185,9 +172,7 @@ describe('isUnsafeAssignment', () => { 'const test: unknown = [] as any;', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('any[] in a generic position to a unknown[]', () => { @@ -195,9 +180,7 @@ describe('isUnsafeAssignment', () => { 'const test: unknown[] = [] as any[]', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); it('any in a generic position to a unknown (nested)', () => { @@ -205,9 +188,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); }); }); }); From bed4a9e4247ff920c8514697644ed2e3571551b4 Mon Sep 17 00:00:00 2001 From: detljh Date: Mon, 7 Jun 2021 17:25:55 +1000 Subject: [PATCH 05/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- .../eslint-utils}/isUnsafeAssignment.test.ts | 57 ++++++++++++------- 1 file changed, 38 insertions(+), 19 deletions(-) rename packages/{eslint-plugin/tests/util => experimental-utils/tests/eslint-utils}/isUnsafeAssignment.test.ts (75%) diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts similarity index 75% rename from packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts rename to packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts index 95780856bc3..a0ddf4518f8 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts @@ -1,9 +1,8 @@ import * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; +import { getFixturesRootDir } from '@typescript-eslint/eslint-plugin/tests/RuleTester'; import path from 'path'; -import { getFixturesRootDir } from '../RuleTester'; -import { isUnsafeAssignment } from '../../src/util'; +import { ESLintUtils, TSESTree } from '../../src'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -34,7 +33,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, @@ -52,7 +51,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'any', 'string', @@ -65,7 +64,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Set', 'Set', @@ -78,7 +77,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Map', 'Map', @@ -91,7 +90,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Set', 'Set', @@ -104,7 +103,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), checker, 'Set>>', 'Set>>', @@ -118,13 +117,17 @@ describe('isUnsafeAssignment', () => { 'const test: string = "";', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any to a any', () => { const { sender, receiver, checker } = getTypes('const test: any = "";'); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any', () => { @@ -132,7 +135,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (multiple generics)', () => { @@ -140,7 +145,9 @@ describe('isUnsafeAssignment', () => { 'const test: Map = new Map();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any[] in a generic position to a non-any[]', () => { @@ -148,7 +155,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (nested)', () => { @@ -156,7 +165,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('non-any in a generic position to a any (nested)', () => { @@ -164,7 +175,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('any to a unknown', () => { @@ -172,7 +185,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown = [] as any;', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('any[] in a generic position to a unknown[]', () => { @@ -180,7 +195,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown[] = [] as any[]', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); it('any in a generic position to a unknown (nested)', () => { @@ -188,7 +205,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker), + ).toBeFalsy(); }); }); }); From 137e3fda93f1c57e0293e78cca00da007d08471a Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Mon, 26 Apr 2021 14:29:34 +1000 Subject: [PATCH 06/15] chore(experimental-utils): moved types eslint-plugin util to experimental-utils package --- .../eslint-plugin/src/rules/await-thenable.ts | 5 +- .../src/rules/no-base-to-string.ts | 11 +++- .../src/rules/no-confusing-void-expression.ts | 3 +- .../src/rules/no-for-in-array.ts | 5 +- .../src/rules/no-throw-literal.ts | 5 +- .../no-unnecessary-boolean-literal-compare.ts | 3 +- .../src/rules/no-unnecessary-condition.ts | 56 +++++++++++-------- .../rules/no-unnecessary-type-assertion.ts | 22 +++++--- .../src/rules/no-unsafe-argument.ts | 13 +++-- .../src/rules/no-unsafe-assignment.ts | 27 +++++---- .../eslint-plugin/src/rules/no-unsafe-call.ts | 10 ++-- .../src/rules/no-unsafe-member-access.ts | 9 +-- .../src/rules/no-unsafe-return.ts | 24 ++++---- .../src/rules/no-unused-vars-experimental.ts | 9 ++- .../src/rules/prefer-includes.ts | 10 +--- .../src/rules/prefer-nullish-coalescing.ts | 5 +- .../src/rules/prefer-readonly.ts | 4 +- .../src/rules/prefer-reduce-type-parameter.ts | 3 +- .../src/rules/prefer-regexp-exec.ts | 6 +- .../rules/prefer-string-starts-ends-with.ts | 4 +- .../src/rules/promise-function-async.ts | 8 ++- .../src/rules/require-array-sort-compare.ts | 10 ++-- .../src/rules/restrict-plus-operands.ts | 9 ++- .../rules/restrict-template-expressions.ts | 16 ++++-- .../eslint-plugin/src/rules/return-await.ts | 3 +- .../src/rules/strict-boolean-expressions.ts | 17 ++++-- .../src/rules/switch-exhaustiveness-check.ts | 9 ++- packages/eslint-plugin/src/util/index.ts | 1 - .../src/eslint-utils/index.ts | 1 + .../src/eslint-utils}/types.ts | 2 +- .../typings/typescript.d.ts | 33 +++++++++++ 31 files changed, 219 insertions(+), 124 deletions(-) rename packages/{eslint-plugin/src/util => experimental-utils/src/eslint-utils}/types.ts (99%) create mode 100644 packages/experimental-utils/typings/typescript.d.ts diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 9858bad8ba2..97cdc093f6f 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,3 +1,4 @@ +import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -29,8 +30,8 @@ export default util.createRule({ const type = checker.getTypeAtLocation(originalNode.expression); if ( - !util.isTypeAnyType(type) && - !util.isTypeUnknownType(type) && + !ESLintUtils.isTypeAnyType(type) && + !ESLintUtils.isTypeUnknownType(type) && !tsutils.isThenableType(checker, originalNode.expression, type) ) { context.report({ 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 b1593c23d8b..ca1fb9af218 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; @@ -99,7 +100,9 @@ export default util.createRule({ return Usefulness.Always; } - if (ignoredTypeNames.includes(util.getTypeName(typeChecker, type))) { + if ( + ignoredTypeNames.includes(ESLintUtils.getTypeName(typeChecker, type)) + ) { return Usefulness.Always; } @@ -165,9 +168,11 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node.right), ); - if (util.getTypeName(typeChecker, leftType) === 'string') { + if (ESLintUtils.getTypeName(typeChecker, leftType) === 'string') { checkExpression(node.right, rightType); - } else if (util.getTypeName(typeChecker, rightType) === 'string') { + } else if ( + ESLintUtils.getTypeName(typeChecker, rightType) === 'string' + ) { checkExpression(node.left, leftType); } }, 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 a9b715350e9..c2d7e540764 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -85,7 +86,7 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(checker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; 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 f89d2ffd08d..3e17d7ed90d 100644 --- a/packages/eslint-plugin/src/rules/no-for-in-array.ts +++ b/packages/eslint-plugin/src/rules/no-for-in-array.ts @@ -1,3 +1,4 @@ +import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -25,13 +26,13 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation( + const type = ESLintUtils.getConstrainedTypeAtLocation( checker, originalNode.expression, ); if ( - util.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || + ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || (type.flags & ts.TypeFlags.StringLike) !== 0 ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index 92bf3b02a13..a2a427c6b1e 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -3,6 +3,7 @@ import * as util from '../util'; import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; export default util.createRule({ @@ -79,8 +80,8 @@ export default util.createRule({ } if ( - util.isTypeAnyType(type) || - util.isTypeUnknownType(type) || + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type) || isErrorLike(type) ) { return; 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 fe1fd24cc4f..953debe328e 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,7 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -159,7 +160,7 @@ export default util.createRule({ function deconstructComparison( node: TSESTree.BinaryExpression, ): BooleanComparison | undefined { - const comparisonType = util.getEqualsKind(node.operator); + const comparisonType = ESLintUtils.getEqualsKind(node.operator); if (!comparisonType) { return undefined; } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 9079769c216..dd541f88def 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -2,6 +2,7 @@ import { TSESTree, AST_NODE_TYPES, AST_TOKEN_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { @@ -13,17 +14,11 @@ import { isStrictCompilerOptionEnabled, } from 'tsutils'; import { - isTypeFlagSet, createRule, getParserServices, - getConstrainedTypeAtLocation, - isNullableType, nullThrows, NullThrowsReasons, isIdentifier, - isTypeAnyType, - isTypeUnknownType, - getTypeName, getTypeOfPropertyOfName, } from '../util'; @@ -37,7 +32,7 @@ const isPossiblyFalsy = (type: ts.Type): boolean => // PossiblyFalsy flag includes literal values, so exclude ones that // are definitely truthy .filter(t => !isTruthyLiteral(t)) - .some(type => isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); + .some(type => ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); const isPossiblyTruthy = (type: ts.Type): boolean => unionTypeParts(type).some(type => !isFalsyType(type)); @@ -45,7 +40,7 @@ const isPossiblyTruthy = (type: ts.Type): boolean => // Nullish utilities const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; const isNullishType = (type: ts.Type): boolean => - isTypeFlagSet(type, nullishFlag); + ESLintUtils.isTypeFlagSet(type, nullishFlag); const isPossiblyNullish = (type: ts.Type): boolean => unionTypeParts(type).some(isNullishType); @@ -169,7 +164,7 @@ export default createRule({ function getNodeType(node: TSESTree.Node): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return getConstrainedTypeAtLocation(checker, tsNode); + return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); } function nodeIsArrayType(node: TSESTree.Expression): boolean { @@ -238,16 +233,16 @@ export default createRule({ if ( unionTypeParts(type).some( part => - isTypeAnyType(part) || - isTypeUnknownType(part) || - isTypeFlagSet(part, ts.TypeFlags.TypeParameter), + ESLintUtils.isTypeAnyType(part) || + ESLintUtils.isTypeUnknownType(part) || + ESLintUtils.isTypeFlagSet(part, ts.TypeFlags.TypeParameter), ) ) { return; } let messageId: MessageId | null = null; - if (isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyTruthy(type)) { messageId = !isUnaryNotArgument ? 'alwaysFalsy' : 'alwaysTruthy'; @@ -269,12 +264,15 @@ export default createRule({ } const type = getNodeType(node); // Conditional is always necessary if it involves `any` or `unknown` - if (isTypeAnyType(type) || isTypeUnknownType(type)) { + if ( + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type) + ) { return; } let messageId: MessageId | null = null; - if (isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyNullish(type)) { messageId = 'neverNullish'; @@ -335,7 +333,7 @@ export default createRule({ flag |= NULL | UNDEFINED; } - return isTypeFlagSet(type, flag); + return ESLintUtils.isTypeFlagSet(type, flag); }; if ( @@ -451,7 +449,12 @@ export default createRule({ return; } // Predicate is always necessary if it involves `any` or `unknown` - if (returnTypes.some(t => isTypeAnyType(t) || isTypeUnknownType(t))) { + if ( + returnTypes.some( + t => + ESLintUtils.isTypeAnyType(t) || ESLintUtils.isTypeUnknownType(t), + ) + ) { return; } if (!returnTypes.some(isPossiblyFalsy)) { @@ -510,10 +513,10 @@ export default createRule({ propertyType.value.toString(), ); if (propType) { - return isNullableType(propType, { allowUndefined: true }); + return ESLintUtils.isNullableType(propType, { allowUndefined: true }); } } - const typeName = getTypeName(checker, propertyType); + const typeName = ESLintUtils.getTypeName(checker, propertyType); return !!( (typeName === 'string' && checker.getIndexInfoOfType(objType, ts.IndexKind.String)) || @@ -546,10 +549,14 @@ export default createRule({ type, property.name, ); - return propType && isNullableType(propType, { allowUndefined: true }); + return ( + propType && + ESLintUtils.isNullableType(propType, { allowUndefined: true }) + ); }); return ( - !isOwnNullable && isNullableType(prevType, { allowUndefined: true }) + !isOwnNullable && + ESLintUtils.isNullableType(prevType, { allowUndefined: true }) ); } return false; @@ -564,9 +571,10 @@ export default createRule({ ? !isNullableOriginFromPrev(node) : true; return ( - isTypeAnyType(type) || - isTypeUnknownType(type) || - (isNullableType(type, { allowUndefined: true }) && isOwnNullable) + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type) || + (ESLintUtils.isNullableType(type, { allowUndefined: true }) && + isOwnNullable) ); } 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 d16f494fc4a..cffad83f637 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { isObjectType, @@ -93,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: ts.Expression): boolean { - const declaration = util.getDeclaration(checker, node); + const declaration = ESLintUtils.getDeclaration(checker, node); if (!declaration) { // don't know what the declaration is for some reason, so just assume the worst return true; @@ -112,7 +113,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(checker, node); + const type = ESLintUtils.getConstrainedTypeAtLocation(checker, 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 @@ -160,12 +161,12 @@ export default util.createRule({ const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation( + const type = ESLintUtils.getConstrainedTypeAtLocation( checker, originalNode.expression, ); - if (!util.isNullableType(type)) { + if (!ESLintUtils.isNullableType(type)) { if (isPossiblyUsedBeforeAssigned(originalNode.expression)) { return; } @@ -184,24 +185,27 @@ 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 = ESLintUtils.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 = ESLintUtils.isTypeFlagSet( type, ts.TypeFlags.Undefined, ); - const typeIncludesNull = util.isTypeFlagSet( + const typeIncludesNull = ESLintUtils.isTypeFlagSet( type, ts.TypeFlags.Null, ); - const contextualTypeIncludesUndefined = util.isTypeFlagSet( + const contextualTypeIncludesUndefined = ESLintUtils.isTypeFlagSet( contextualType, ts.TypeFlags.Undefined, ); - const contextualTypeIncludesNull = util.isTypeFlagSet( + const contextualTypeIncludesNull = ESLintUtils.isTypeFlagSet( contextualType, ts.TypeFlags.Null, ); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts index aef8f927bea..0c0e2b0ca2b 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts @@ -1,6 +1,7 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -168,7 +169,7 @@ export default util.createRule<[], MessageIds>({ // ignore any-typed calls as these are caught by no-unsafe-call if ( - util.isTypeAnyType( + ESLintUtils.isTypeAnyType( checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(node.callee)), ) ) { @@ -191,13 +192,15 @@ export default util.createRule<[], MessageIds>({ esTreeNodeToTSNodeMap.get(argument.argument), ); - if (util.isTypeAnyType(spreadArgType)) { + if (ESLintUtils.isTypeAnyType(spreadArgType)) { // foo(...any) context.report({ node: argument, messageId: 'unsafeSpread', }); - } else if (util.isTypeAnyArrayType(spreadArgType, checker)) { + } else if ( + ESLintUtils.isTypeAnyArrayType(spreadArgType, checker) + ) { // foo(...any[]) // TODO - we could break down the spread and compare the array type against each argument @@ -215,7 +218,7 @@ export default util.createRule<[], MessageIds>({ if (parameterType == null) { continue; } - const result = util.isUnsafeAssignment( + const result = ESLintUtils.isUnsafeAssignment( tupleType, parameterType, checker, @@ -256,7 +259,7 @@ export default util.createRule<[], MessageIds>({ const argumentType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(argument), ); - const result = util.isUnsafeAssignment( + const result = ESLintUtils.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 ae900b14f0c..05ac8c3eead 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -74,7 +75,7 @@ export default util.createRule({ ): boolean { // any array // const [x] = ([] as any[]); - if (util.isTypeAnyArrayType(senderType, checker)) { + if (ESLintUtils.isTypeAnyArrayType(senderType, checker)) { context.report({ node: receiverNode, messageId: 'unsafeArrayPattern', @@ -86,7 +87,7 @@ export default util.createRule({ return true; } - const tupleElements = util.getTypeArguments(senderType, checker); + const tupleElements = ESLintUtils.getTypeArguments(senderType, checker); // tuple with any // const [x] = [1 as any]; @@ -112,7 +113,7 @@ export default util.createRule({ } // check for the any type first so we can handle [[[x]]] = [any] - if (util.isTypeAnyType(senderType)) { + if (ESLintUtils.isTypeAnyType(senderType)) { context.report({ node: receiverElement, messageId: 'unsafeArrayPatternFromTuple', @@ -203,7 +204,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 (ESLintUtils.isTypeAnyType(senderType)) { context.report({ node: receiverProperty.value, messageId: 'unsafeArrayPatternFromTuple', @@ -241,16 +242,18 @@ export default util.createRule({ const receiverTsNode = esTreeNodeToTSNodeMap.get(receiverNode); const receiverType = comparisonType === ComparisonType.Contextual - ? util.getContextualType(checker, receiverTsNode as ts.Expression) ?? - checker.getTypeAtLocation(receiverTsNode) + ? ESLintUtils.getContextualType( + checker, + receiverTsNode as ts.Expression, + ) ?? checker.getTypeAtLocation(receiverTsNode) : checker.getTypeAtLocation(receiverTsNode); const senderType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(senderNode), ); - if (util.isTypeAnyType(senderType)) { + if (ESLintUtils.isTypeAnyType(senderType)) { // handle cases when we assign any ==> unknown. - if (util.isTypeUnknownType(receiverType)) { + if (ESLintUtils.isTypeUnknownType(receiverType)) { return false; } @@ -261,8 +264,8 @@ export default util.createRule({ const thisExpression = getThisExpression(senderNode); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -379,8 +382,8 @@ export default util.createRule({ const resetNode = esTreeNodeToTSNodeMap.get(node.argument); const restType = checker.getTypeAtLocation(resetNode); if ( - util.isTypeAnyType(restType) || - util.isTypeAnyArrayType(restType, checker) + ESLintUtils.isTypeAnyType(restType) || + ESLintUtils.isTypeAnyArrayType(restType, checker) ) { context.report({ node: node, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-call.ts b/packages/eslint-plugin/src/rules/no-unsafe-call.ts index b08214d36c2..7a9bdf0fe39 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-call.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-call.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; import { getThisExpression } from '../util'; @@ -46,16 +46,16 @@ export default util.createRule<[], MessageIds>({ messageId: MessageIds, ): void { const tsNode = esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(checker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); - if (util.isTypeAnyType(type)) { + if (ESLintUtils.isTypeAnyType(type)) { if (!isNoImplicitThis) { // `this()` or `this.foo()` or `this.foo[bar]()` const thisExpression = getThisExpression(node); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), 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 121e826053e..2d29db21ef6 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,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -64,7 +65,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node.object); const type = checker.getTypeAtLocation(tsNode); - const state = util.isTypeAnyType(type) ? State.Unsafe : State.Safe; + const state = ESLintUtils.isTypeAnyType(type) ? State.Unsafe : State.Safe; stateCache.set(node, state); if (state === State.Unsafe) { @@ -79,8 +80,8 @@ export default util.createRule({ if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -124,7 +125,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(tsNode); - if (util.isTypeAnyType(type)) { + if (ESLintUtils.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 d460dd04c9b..d5223c1cc88 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-return.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-return.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -67,14 +68,17 @@ export default util.createRule({ reportingNode: TSESTree.Node = returnNode, ): void { const tsNode = esTreeNodeToTSNodeMap.get(returnNode); - const anyType = util.isAnyOrAnyArrayTypeDiscriminated(tsNode, checker); + const anyType = ESLintUtils.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( + const returnNodeType = ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(returnNode), ); @@ -85,7 +89,7 @@ export default util.createRule({ // 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) - ? util.getContextualType(checker, functionTSNode) + ? ESLintUtils.getContextualType(checker, functionTSNode) : checker.getTypeAtLocation(functionTSNode); if (!functionType) { functionType = checker.getTypeAtLocation(functionTSNode); @@ -107,14 +111,14 @@ export default util.createRule({ for (const signature of functionType.getCallSignatures()) { const functionReturnType = signature.getReturnType(); if ( - anyType === util.AnyType.Any && - util.isTypeUnknownType(functionReturnType) + anyType === ESLintUtils.AnyType.Any && + ESLintUtils.isTypeUnknownType(functionReturnType) ) { return; } if ( - anyType === util.AnyType.AnyArray && - util.isTypeUnknownArrayType(functionReturnType, checker) + anyType === ESLintUtils.AnyType.AnyArray && + ESLintUtils.isTypeUnknownArrayType(functionReturnType, checker) ) { return; } @@ -127,8 +131,8 @@ export default util.createRule({ const thisExpression = getThisExpression(returnNode); if ( thisExpression && - util.isTypeAnyType( - util.getConstrainedTypeAtLocation( + ESLintUtils.isTypeAnyType( + ESLintUtils.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -143,7 +147,7 @@ export default util.createRule({ node: reportingNode, messageId, data: { - type: anyType === util.AnyType.Any ? 'any' : 'any[]', + type: anyType === ESLintUtils.AnyType.Any ? 'any' : 'any[]', }, }); } diff --git a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts index 0aedd20cbb2..5a6114de5f3 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts @@ -1,6 +1,6 @@ /* eslint-disable no-fallthrough */ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -294,13 +294,16 @@ export default util.createRule({ return { 'Program:exit'(program: TSESTree.Program): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(program); - const sourceFile = util.getSourceFileOfNode(tsNode); + const sourceFile = ESLintUtils.getSourceFileOfNode(tsNode); const diagnostics = tsProgram.getSemanticDiagnostics(sourceFile); diagnostics.forEach(diag => { if (isUnusedDiagnostic(diag.code)) { if (diag.start !== undefined) { - const node = util.getTokenAtPosition(sourceFile, diag.start); + const node = ESLintUtils.getTokenAtPosition( + sourceFile, + diag.start, + ); const parent = node.parent; if (isIdentifier(node)) { handleIdentifier(node); diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index 13a6021c806..9137ce51de0 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -2,15 +2,11 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, parseRegExpLiteral } from 'regexpp'; import * as ts from 'typescript'; -import { - createRule, - getParserServices, - getStaticValue, - getConstrainedTypeAtLocation, -} from '../util'; +import { createRule, getParserServices, getStaticValue } from '../util'; export default createRule({ name: 'prefer-includes', @@ -217,7 +213,7 @@ export default createRule({ //check the argument type of test methods const argument = callNode.arguments[0]; const tsNode = services.esTreeNodeToTSNodeMap.get(argument); - const type = getConstrainedTypeAtLocation(types, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation(types, tsNode); const includesMethodDecl = type .getProperty('includes') diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index fa6c1bb4e21..6816e9030b2 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -3,6 +3,7 @@ import { AST_TOKEN_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -66,7 +67,9 @@ 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 = ESLintUtils.isNullableType(type, { + allowUndefined: true, + }); if (!isNullish) { return; } diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 56ab8265a9a..0bc9f7dde2c 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -1,10 +1,10 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; -import { typeIsOrHasBaseType } from '../util'; import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; type MessageIds = 'preferReadonly'; @@ -321,7 +321,7 @@ class ClassScope { const modifierType = this.checker.getTypeAtLocation(node.expression); if ( !modifierType.getSymbol() || - !typeIsOrHasBaseType(modifierType, this.classType) + !ESLintUtils.typeIsOrHasBaseType(modifierType, this.classType) ) { return; } 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 3b1af79ac6e..fa883a2e8bd 100644 --- a/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts +++ b/packages/eslint-plugin/src/rules/prefer-reduce-type-parameter.ts @@ -1,6 +1,7 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -67,7 +68,7 @@ export default util.createRule({ // Get the symbol of the `reduce` method. const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = util.getConstrainedTypeAtLocation( + const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( checker, tsNode, ); diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index 636fe2b3825..90a2af78e32 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -1,12 +1,12 @@ import { AST_NODE_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { createRule, getParserServices, getStaticValue, - getTypeName, getWrappingFixer, } from '../util'; @@ -44,7 +44,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return getTypeName(typeChecker, objectType) === 'string'; + return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; } /** @@ -55,7 +55,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return getTypeName(typeChecker, objectType) === 'RegExp'; + return ESLintUtils.getTypeName(typeChecker, objectType) === 'RegExp'; } return { diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index f4697b7c01d..986f7279b45 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, RegExpParser } from 'regexpp'; import { @@ -9,7 +10,6 @@ import { getParserServices, getPropertyName, getStaticValue, - getTypeName, isNotClosingParenToken, nullThrows, NullThrowsReasons, @@ -53,7 +53,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( service.esTreeNodeToTSNodeMap.get(node), ); - return getTypeName(typeChecker, objectType) === 'string'; + return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; } /** diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index 68b1d42567c..d96d4b05008 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -110,7 +111,7 @@ export default util.createRule({ const returnType = checker.getReturnTypeOfSignature(signatures[0]); if ( - !util.containsAllTypesByName( + !ESLintUtils.containsAllTypesByName( returnType, allowAny!, allAllowedPromiseNames, @@ -136,7 +137,10 @@ export default util.createRule({ } if ( - util.isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown) + ESLintUtils.isTypeFlagSet( + returnType, + ts.TypeFlags.Any | ts.TypeFlags.Unknown, + ) ) { // Report without auto fixer because the return type is unknown return context.report({ 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 6e0c49f31a8..0fa4fae7e12 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export type Options = [ @@ -55,7 +55,7 @@ export default util.createRule({ if (checker.isArrayType(type) || checker.isTupleType(type)) { const typeArgs = checker.getTypeArguments(type); return typeArgs.every( - arg => util.getTypeName(checker, arg) === 'string', + arg => ESLintUtils.getTypeName(checker, arg) === 'string', ); } return false; @@ -66,7 +66,7 @@ export default util.createRule({ callee: TSESTree.MemberExpression, ): void { const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = util.getConstrainedTypeAtLocation( + const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( checker, tsNode, ); @@ -75,7 +75,9 @@ export default util.createRule({ return; } - if (util.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) { + if ( + ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker) + ) { context.report({ node: callee.parent!, messageId: 'requireCompare' }); } }, diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index 0f3b07e9fb2..fe40dd81068 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -59,7 +59,7 @@ export default util.createRule({ } if ( type.isStringLiteral() || - util.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) + ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) ) { return 'string'; } @@ -96,7 +96,10 @@ export default util.createRule({ */ function getNodeType(node: TSESTree.Expression): BaseLiteral { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation( + typeChecker, + tsNode, + ); return getBaseTypeOfLiteralType(type); } diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index a4756266ffc..e969d559219 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -1,6 +1,7 @@ import { TSESTree, AST_NODE_TYPES, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -51,13 +52,13 @@ export default util.createRule({ const typeChecker = service.program.getTypeChecker(); function isUnderlyingTypePrimitive(type: ts.Type): boolean { - if (util.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { + if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { return true; } if ( options.allowNumber && - util.isTypeFlagSet( + ESLintUtils.isTypeFlagSet( type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ) @@ -67,18 +68,21 @@ export default util.createRule({ if ( options.allowBoolean && - util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) + ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) ) { return true; } - if (options.allowAny && util.isTypeAnyType(type)) { + if (options.allowAny && ESLintUtils.isTypeAnyType(type)) { return true; } if ( options.allowNullish && - util.isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined) + ESLintUtils.isTypeFlagSet( + type, + ts.TypeFlags.Null | ts.TypeFlags.Undefined, + ) ) { return true; } @@ -94,7 +98,7 @@ export default util.createRule({ } for (const expression of node.expressions) { - const expressionType = util.getConstrainedTypeAtLocation( + const expressionType = ESLintUtils.getConstrainedTypeAtLocation( typeChecker, service.esTreeNodeToTSNodeMap.get(expression), ); diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index 85a2eebe1f5..ad7a7ba8a15 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -172,7 +173,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) + ESLintUtils.isTypeAnyType(type) || ESLintUtils.isTypeUnknownType(type) ); const fix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix | null => removeAwait(fixer, node); diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 87796f9f427..55d3f89d647 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -2,6 +2,7 @@ import { AST_NODE_TYPES, ParserServices, TSESTree, + ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -225,7 +226,10 @@ export default util.createRule({ } const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); + const type = ESLintUtils.getConstrainedTypeAtLocation( + typeChecker, + tsNode, + ); const types = inspectVariantTypes(tsutils.unionTypeParts(type)); const is = (...wantedTypes: readonly VariantType[]): boolean => @@ -790,7 +794,9 @@ export default util.createRule({ if ( types.some( - type => util.isTypeAnyType(type) || util.isTypeUnknownType(type), + type => + ESLintUtils.isTypeAnyType(type) || + ESLintUtils.isTypeUnknownType(type), ) ) { variantTypes.add('any'); @@ -826,9 +832,12 @@ function isArrayLengthExpression( return false; } const objectTsNode = parserServices.esTreeNodeToTSNodeMap.get(node.object); - const objectType = util.getConstrainedTypeAtLocation( + const objectType = ESLintUtils.getConstrainedTypeAtLocation( typeChecker, objectTsNode, ); - return util.isTypeArrayTypeOrUnionOfArrayTypes(objectType, typeChecker); + return ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes( + objectType, + typeChecker, + ); } diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index 8881473da05..cd86d2ced8a 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -1,8 +1,11 @@ -import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + TSESLint, + TSESTree, + ESLintUtils, +} from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { createRule, - getConstrainedTypeAtLocation, getParserServices, isClosingBraceToken, isOpeningBraceToken, @@ -37,7 +40,7 @@ export default createRule({ function getNodeType(node: TSESTree.Node): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return getConstrainedTypeAtLocation(checker, tsNode); + return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); } function fixSwitch( diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 4c028489523..6f616d0c851 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -12,7 +12,6 @@ export * from './nullThrows'; export * from './objectIterators'; export * from './propertyTypes'; export * from './requiresQuoting'; -export * from './types'; // this is done for convenience - saves migrating all of the old rules const { applyDefault, deepMerge, isObjectNotArray, getParserServices } = diff --git a/packages/experimental-utils/src/eslint-utils/index.ts b/packages/experimental-utils/src/eslint-utils/index.ts index bbbe8df2709..2381db1d373 100644 --- a/packages/experimental-utils/src/eslint-utils/index.ts +++ b/packages/experimental-utils/src/eslint-utils/index.ts @@ -5,3 +5,4 @@ export * from './InferTypesFromRule'; export * from './RuleCreator'; export * from './RuleTester'; export * from './deepMerge'; +export * from './types'; diff --git a/packages/eslint-plugin/src/util/types.ts b/packages/experimental-utils/src/eslint-utils/types.ts similarity index 99% rename from packages/eslint-plugin/src/util/types.ts rename to packages/experimental-utils/src/eslint-utils/types.ts index 089620e702a..5da17a5e413 100644 --- a/packages/eslint-plugin/src/util/types.ts +++ b/packages/experimental-utils/src/eslint-utils/types.ts @@ -19,7 +19,7 @@ import { } from 'tsutils'; import * as ts from 'typescript'; -const log = debug('typescript-eslint:eslint-plugin:utils:types'); +const log = debug('typescript-eslint:experimental-utils:eslint-utils:types'); /** * Checks if the given type is either an array type, diff --git a/packages/experimental-utils/typings/typescript.d.ts b/packages/experimental-utils/typings/typescript.d.ts new file mode 100644 index 00000000000..73304155ee7 --- /dev/null +++ b/packages/experimental-utils/typings/typescript.d.ts @@ -0,0 +1,33 @@ +import 'typescript'; + +declare module 'typescript' { + interface TypeChecker { + // internal TS APIs + + /** + * @returns `true` if the given type is an array type: + * - `Array` + * - `ReadonlyArray` + * - `foo[]` + * - `readonly foo[]` + */ + isArrayType(type: Type): type is TypeReference; + /** + * @returns `true` if the given type is a tuple type: + * - `[foo]` + * - `readonly [foo]` + */ + isTupleType(type: Type): type is TupleTypeReference; + /** + * Return the type of the given property in the given type, or undefined if no such property exists + */ + getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; + } + + interface Type { + /** + * If the type is `any`, and this is set to "error", then TS was unable to resolve the type + */ + intrinsicName?: string; + } +} From 9f4a4d6b8131dae4315379b07c2fdb465f16438a Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Wed, 19 May 2021 15:26:56 +1000 Subject: [PATCH 07/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- packages/eslint-plugin/src/util/index.ts | 1 + packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 6f616d0c851..4842e84facd 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -12,6 +12,7 @@ export * from './nullThrows'; export * from './objectIterators'; export * from './propertyTypes'; export * from './requiresQuoting'; +export * from '@typescript-eslint/experimental-utils/dist/eslint-utils/types'; // this is done for convenience - saves migrating all of the old rules const { applyDefault, deepMerge, isObjectNotArray, getParserServices } = diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts index 1d4946a964d..d42f91eeb59 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts @@ -1,9 +1,8 @@ import * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'path'; import { getFixturesRootDir } from '../RuleTester'; -import { isUnsafeAssignment } from '../../src/util/types'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -38,7 +37,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, From eea8ef68327e7c889db94a4dc4b3a9b3f4dc9d62 Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Tue, 1 Jun 2021 18:24:29 +1000 Subject: [PATCH 08/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- .../eslint-plugin/src/rules/await-thenable.ts | 5 +- .../src/rules/no-base-to-string.ts | 11 +--- .../src/rules/no-confusing-void-expression.ts | 3 +- .../src/rules/no-for-in-array.ts | 5 +- .../src/rules/no-throw-literal.ts | 5 +- .../no-unnecessary-boolean-literal-compare.ts | 3 +- .../src/rules/no-unnecessary-condition.ts | 56 ++++++++----------- .../rules/no-unnecessary-type-assertion.ts | 22 +++----- .../src/rules/no-unsafe-argument.ts | 13 ++--- .../src/rules/no-unsafe-assignment.ts | 27 ++++----- .../eslint-plugin/src/rules/no-unsafe-call.ts | 10 ++-- .../src/rules/no-unsafe-member-access.ts | 9 ++- .../src/rules/no-unsafe-return.ts | 24 ++++---- .../src/rules/no-unused-vars-experimental.ts | 9 +-- .../src/rules/prefer-includes.ts | 10 +++- .../src/rules/prefer-nullish-coalescing.ts | 5 +- .../src/rules/prefer-readonly.ts | 4 +- .../src/rules/prefer-reduce-type-parameter.ts | 3 +- .../src/rules/prefer-regexp-exec.ts | 6 +- .../rules/prefer-string-starts-ends-with.ts | 4 +- .../src/rules/promise-function-async.ts | 8 +-- .../src/rules/require-array-sort-compare.ts | 10 ++-- .../src/rules/restrict-plus-operands.ts | 9 +-- .../rules/restrict-template-expressions.ts | 16 ++---- .../eslint-plugin/src/rules/return-await.ts | 3 +- .../src/rules/strict-boolean-expressions.ts | 17 ++---- .../src/rules/switch-exhaustiveness-check.ts | 9 +-- 27 files changed, 122 insertions(+), 184 deletions(-) diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 97cdc093f6f..9858bad8ba2 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,4 +1,3 @@ -import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -30,8 +29,8 @@ export default util.createRule({ const type = checker.getTypeAtLocation(originalNode.expression); if ( - !ESLintUtils.isTypeAnyType(type) && - !ESLintUtils.isTypeUnknownType(type) && + !util.isTypeAnyType(type) && + !util.isTypeUnknownType(type) && !tsutils.isThenableType(checker, originalNode.expression, type) ) { context.report({ 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 ca1fb9af218..b1593c23d8b 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; @@ -100,9 +99,7 @@ export default util.createRule({ return Usefulness.Always; } - if ( - ignoredTypeNames.includes(ESLintUtils.getTypeName(typeChecker, type)) - ) { + if (ignoredTypeNames.includes(util.getTypeName(typeChecker, type))) { return Usefulness.Always; } @@ -168,11 +165,9 @@ export default util.createRule({ parserServices.esTreeNodeToTSNodeMap.get(node.right), ); - if (ESLintUtils.getTypeName(typeChecker, leftType) === 'string') { + if (util.getTypeName(typeChecker, leftType) === 'string') { checkExpression(node.right, rightType); - } else if ( - ESLintUtils.getTypeName(typeChecker, rightType) === 'string' - ) { + } else if (util.getTypeName(typeChecker, rightType) === 'string') { checkExpression(node.left, leftType); } }, 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 c2d7e540764..a9b715350e9 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -86,7 +85,7 @@ export default util.createRule({ const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + const type = util.getConstrainedTypeAtLocation(checker, tsNode); if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { // not a void expression return; 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 3e17d7ed90d..f89d2ffd08d 100644 --- a/packages/eslint-plugin/src/rules/no-for-in-array.ts +++ b/packages/eslint-plugin/src/rules/no-for-in-array.ts @@ -1,4 +1,3 @@ -import { ESLintUtils } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -26,13 +25,13 @@ export default util.createRule({ const checker = parserServices.program.getTypeChecker(); const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( + const type = util.getConstrainedTypeAtLocation( checker, originalNode.expression, ); if ( - ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || + util.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || (type.flags & ts.TypeFlags.StringLike) !== 0 ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index a2a427c6b1e..92bf3b02a13 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -3,7 +3,6 @@ import * as util from '../util'; import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; export default util.createRule({ @@ -80,8 +79,8 @@ export default util.createRule({ } if ( - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type) || + util.isTypeAnyType(type) || + util.isTypeUnknownType(type) || isErrorLike(type) ) { return; 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 953debe328e..fe1fd24cc4f 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,7 +1,6 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -160,7 +159,7 @@ export default util.createRule({ function deconstructComparison( node: TSESTree.BinaryExpression, ): BooleanComparison | undefined { - const comparisonType = ESLintUtils.getEqualsKind(node.operator); + const comparisonType = util.getEqualsKind(node.operator); if (!comparisonType) { return undefined; } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index dd541f88def..9079769c216 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -2,7 +2,6 @@ import { TSESTree, AST_NODE_TYPES, AST_TOKEN_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { @@ -14,11 +13,17 @@ import { isStrictCompilerOptionEnabled, } from 'tsutils'; import { + isTypeFlagSet, createRule, getParserServices, + getConstrainedTypeAtLocation, + isNullableType, nullThrows, NullThrowsReasons, isIdentifier, + isTypeAnyType, + isTypeUnknownType, + getTypeName, getTypeOfPropertyOfName, } from '../util'; @@ -32,7 +37,7 @@ const isPossiblyFalsy = (type: ts.Type): boolean => // PossiblyFalsy flag includes literal values, so exclude ones that // are definitely truthy .filter(t => !isTruthyLiteral(t)) - .some(type => ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); + .some(type => isTypeFlagSet(type, ts.TypeFlags.PossiblyFalsy)); const isPossiblyTruthy = (type: ts.Type): boolean => unionTypeParts(type).some(type => !isFalsyType(type)); @@ -40,7 +45,7 @@ const isPossiblyTruthy = (type: ts.Type): boolean => // Nullish utilities const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; const isNullishType = (type: ts.Type): boolean => - ESLintUtils.isTypeFlagSet(type, nullishFlag); + isTypeFlagSet(type, nullishFlag); const isPossiblyNullish = (type: ts.Type): boolean => unionTypeParts(type).some(isNullishType); @@ -164,7 +169,7 @@ export default createRule({ function getNodeType(node: TSESTree.Node): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + return getConstrainedTypeAtLocation(checker, tsNode); } function nodeIsArrayType(node: TSESTree.Expression): boolean { @@ -233,16 +238,16 @@ export default createRule({ if ( unionTypeParts(type).some( part => - ESLintUtils.isTypeAnyType(part) || - ESLintUtils.isTypeUnknownType(part) || - ESLintUtils.isTypeFlagSet(part, ts.TypeFlags.TypeParameter), + isTypeAnyType(part) || + isTypeUnknownType(part) || + isTypeFlagSet(part, ts.TypeFlags.TypeParameter), ) ) { return; } let messageId: MessageId | null = null; - if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyTruthy(type)) { messageId = !isUnaryNotArgument ? 'alwaysFalsy' : 'alwaysTruthy'; @@ -264,15 +269,12 @@ export default createRule({ } const type = getNodeType(node); // Conditional is always necessary if it involves `any` or `unknown` - if ( - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type) - ) { + if (isTypeAnyType(type) || isTypeUnknownType(type)) { return; } let messageId: MessageId | null = null; - if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.Never)) { + if (isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyNullish(type)) { messageId = 'neverNullish'; @@ -333,7 +335,7 @@ export default createRule({ flag |= NULL | UNDEFINED; } - return ESLintUtils.isTypeFlagSet(type, flag); + return isTypeFlagSet(type, flag); }; if ( @@ -449,12 +451,7 @@ export default createRule({ return; } // Predicate is always necessary if it involves `any` or `unknown` - if ( - returnTypes.some( - t => - ESLintUtils.isTypeAnyType(t) || ESLintUtils.isTypeUnknownType(t), - ) - ) { + if (returnTypes.some(t => isTypeAnyType(t) || isTypeUnknownType(t))) { return; } if (!returnTypes.some(isPossiblyFalsy)) { @@ -513,10 +510,10 @@ export default createRule({ propertyType.value.toString(), ); if (propType) { - return ESLintUtils.isNullableType(propType, { allowUndefined: true }); + return isNullableType(propType, { allowUndefined: true }); } } - const typeName = ESLintUtils.getTypeName(checker, propertyType); + const typeName = getTypeName(checker, propertyType); return !!( (typeName === 'string' && checker.getIndexInfoOfType(objType, ts.IndexKind.String)) || @@ -549,14 +546,10 @@ export default createRule({ type, property.name, ); - return ( - propType && - ESLintUtils.isNullableType(propType, { allowUndefined: true }) - ); + return propType && isNullableType(propType, { allowUndefined: true }); }); return ( - !isOwnNullable && - ESLintUtils.isNullableType(prevType, { allowUndefined: true }) + !isOwnNullable && isNullableType(prevType, { allowUndefined: true }) ); } return false; @@ -571,10 +564,9 @@ export default createRule({ ? !isNullableOriginFromPrev(node) : true; return ( - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type) || - (ESLintUtils.isNullableType(type, { allowUndefined: true }) && - isOwnNullable) + isTypeAnyType(type) || + isTypeUnknownType(type) || + (isNullableType(type, { allowUndefined: true }) && isOwnNullable) ); } 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 cffad83f637..d16f494fc4a 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-type-assertion.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { isObjectType, @@ -94,7 +93,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: ts.Expression): boolean { - const declaration = ESLintUtils.getDeclaration(checker, node); + const declaration = util.getDeclaration(checker, node); if (!declaration) { // don't know what the declaration is for some reason, so just assume the worst return true; @@ -113,7 +112,7 @@ export default util.createRule({ ) { // check if the defined variable type has changed since assignment const declarationType = checker.getTypeFromTypeNode(declaration.type); - const type = ESLintUtils.getConstrainedTypeAtLocation(checker, node); + const type = util.getConstrainedTypeAtLocation(checker, 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 @@ -161,12 +160,12 @@ export default util.createRule({ const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( + const type = util.getConstrainedTypeAtLocation( checker, originalNode.expression, ); - if (!ESLintUtils.isNullableType(type)) { + if (!util.isNullableType(type)) { if (isPossiblyUsedBeforeAssigned(originalNode.expression)) { return; } @@ -185,27 +184,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 = ESLintUtils.getContextualType( - checker, - originalNode, - ); + const contextualType = util.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 = ESLintUtils.isTypeFlagSet( + const typeIncludesUndefined = util.isTypeFlagSet( type, ts.TypeFlags.Undefined, ); - const typeIncludesNull = ESLintUtils.isTypeFlagSet( + const typeIncludesNull = util.isTypeFlagSet( type, ts.TypeFlags.Null, ); - const contextualTypeIncludesUndefined = ESLintUtils.isTypeFlagSet( + const contextualTypeIncludesUndefined = util.isTypeFlagSet( contextualType, ts.TypeFlags.Undefined, ); - const contextualTypeIncludesNull = ESLintUtils.isTypeFlagSet( + const contextualTypeIncludesNull = util.isTypeFlagSet( contextualType, ts.TypeFlags.Null, ); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts index 0c0e2b0ca2b..aef8f927bea 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts @@ -1,7 +1,6 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -169,7 +168,7 @@ export default util.createRule<[], MessageIds>({ // ignore any-typed calls as these are caught by no-unsafe-call if ( - ESLintUtils.isTypeAnyType( + util.isTypeAnyType( checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(node.callee)), ) ) { @@ -192,15 +191,13 @@ export default util.createRule<[], MessageIds>({ esTreeNodeToTSNodeMap.get(argument.argument), ); - if (ESLintUtils.isTypeAnyType(spreadArgType)) { + if (util.isTypeAnyType(spreadArgType)) { // foo(...any) context.report({ node: argument, messageId: 'unsafeSpread', }); - } else if ( - ESLintUtils.isTypeAnyArrayType(spreadArgType, checker) - ) { + } else if (util.isTypeAnyArrayType(spreadArgType, checker)) { // foo(...any[]) // TODO - we could break down the spread and compare the array type against each argument @@ -218,7 +215,7 @@ export default util.createRule<[], MessageIds>({ if (parameterType == null) { continue; } - const result = ESLintUtils.isUnsafeAssignment( + const result = util.isUnsafeAssignment( tupleType, parameterType, checker, @@ -259,7 +256,7 @@ export default util.createRule<[], MessageIds>({ const argumentType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(argument), ); - const result = ESLintUtils.isUnsafeAssignment( + const result = util.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 05ac8c3eead..ae900b14f0c 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-assignment.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -75,7 +74,7 @@ export default util.createRule({ ): boolean { // any array // const [x] = ([] as any[]); - if (ESLintUtils.isTypeAnyArrayType(senderType, checker)) { + if (util.isTypeAnyArrayType(senderType, checker)) { context.report({ node: receiverNode, messageId: 'unsafeArrayPattern', @@ -87,7 +86,7 @@ export default util.createRule({ return true; } - const tupleElements = ESLintUtils.getTypeArguments(senderType, checker); + const tupleElements = util.getTypeArguments(senderType, checker); // tuple with any // const [x] = [1 as any]; @@ -113,7 +112,7 @@ export default util.createRule({ } // check for the any type first so we can handle [[[x]]] = [any] - if (ESLintUtils.isTypeAnyType(senderType)) { + if (util.isTypeAnyType(senderType)) { context.report({ node: receiverElement, messageId: 'unsafeArrayPatternFromTuple', @@ -204,7 +203,7 @@ export default util.createRule({ } // check for the any type first so we can handle {x: {y: z}} = {x: any} - if (ESLintUtils.isTypeAnyType(senderType)) { + if (util.isTypeAnyType(senderType)) { context.report({ node: receiverProperty.value, messageId: 'unsafeArrayPatternFromTuple', @@ -242,18 +241,16 @@ export default util.createRule({ const receiverTsNode = esTreeNodeToTSNodeMap.get(receiverNode); const receiverType = comparisonType === ComparisonType.Contextual - ? ESLintUtils.getContextualType( - checker, - receiverTsNode as ts.Expression, - ) ?? checker.getTypeAtLocation(receiverTsNode) + ? util.getContextualType(checker, receiverTsNode as ts.Expression) ?? + checker.getTypeAtLocation(receiverTsNode) : checker.getTypeAtLocation(receiverTsNode); const senderType = checker.getTypeAtLocation( esTreeNodeToTSNodeMap.get(senderNode), ); - if (ESLintUtils.isTypeAnyType(senderType)) { + if (util.isTypeAnyType(senderType)) { // handle cases when we assign any ==> unknown. - if (ESLintUtils.isTypeUnknownType(receiverType)) { + if (util.isTypeUnknownType(receiverType)) { return false; } @@ -264,8 +261,8 @@ export default util.createRule({ const thisExpression = getThisExpression(senderNode); if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -382,8 +379,8 @@ export default util.createRule({ const resetNode = esTreeNodeToTSNodeMap.get(node.argument); const restType = checker.getTypeAtLocation(resetNode); if ( - ESLintUtils.isTypeAnyType(restType) || - ESLintUtils.isTypeAnyArrayType(restType, checker) + util.isTypeAnyType(restType) || + util.isTypeAnyArrayType(restType, checker) ) { context.report({ node: node, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-call.ts b/packages/eslint-plugin/src/rules/no-unsafe-call.ts index 7a9bdf0fe39..b08214d36c2 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-call.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-call.ts @@ -1,4 +1,4 @@ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; import { getThisExpression } from '../util'; @@ -46,16 +46,16 @@ export default util.createRule<[], MessageIds>({ messageId: MessageIds, ): void { const tsNode = esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + const type = util.getConstrainedTypeAtLocation(checker, tsNode); - if (ESLintUtils.isTypeAnyType(type)) { + if (util.isTypeAnyType(type)) { if (!isNoImplicitThis) { // `this()` or `this.foo()` or `this.foo[bar]()` const thisExpression = getThisExpression(node); if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), 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 2d29db21ef6..121e826053e 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -65,7 +64,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node.object); const type = checker.getTypeAtLocation(tsNode); - const state = ESLintUtils.isTypeAnyType(type) ? State.Unsafe : State.Safe; + const state = util.isTypeAnyType(type) ? State.Unsafe : State.Safe; stateCache.set(node, state); if (state === State.Unsafe) { @@ -80,8 +79,8 @@ export default util.createRule({ if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -125,7 +124,7 @@ export default util.createRule({ const tsNode = esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(tsNode); - if (ESLintUtils.isTypeAnyType(type)) { + if (util.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 d5223c1cc88..d460dd04c9b 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-return.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-return.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as util from '../util'; @@ -68,17 +67,14 @@ export default util.createRule({ reportingNode: TSESTree.Node = returnNode, ): void { const tsNode = esTreeNodeToTSNodeMap.get(returnNode); - const anyType = ESLintUtils.isAnyOrAnyArrayTypeDiscriminated( - tsNode, - checker, - ); + const anyType = util.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 = ESLintUtils.getConstrainedTypeAtLocation( + const returnNodeType = util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(returnNode), ); @@ -89,7 +85,7 @@ export default util.createRule({ // 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) - ? ESLintUtils.getContextualType(checker, functionTSNode) + ? util.getContextualType(checker, functionTSNode) : checker.getTypeAtLocation(functionTSNode); if (!functionType) { functionType = checker.getTypeAtLocation(functionTSNode); @@ -111,14 +107,14 @@ export default util.createRule({ for (const signature of functionType.getCallSignatures()) { const functionReturnType = signature.getReturnType(); if ( - anyType === ESLintUtils.AnyType.Any && - ESLintUtils.isTypeUnknownType(functionReturnType) + anyType === util.AnyType.Any && + util.isTypeUnknownType(functionReturnType) ) { return; } if ( - anyType === ESLintUtils.AnyType.AnyArray && - ESLintUtils.isTypeUnknownArrayType(functionReturnType, checker) + anyType === util.AnyType.AnyArray && + util.isTypeUnknownArrayType(functionReturnType, checker) ) { return; } @@ -131,8 +127,8 @@ export default util.createRule({ const thisExpression = getThisExpression(returnNode); if ( thisExpression && - ESLintUtils.isTypeAnyType( - ESLintUtils.getConstrainedTypeAtLocation( + util.isTypeAnyType( + util.getConstrainedTypeAtLocation( checker, esTreeNodeToTSNodeMap.get(thisExpression), ), @@ -147,7 +143,7 @@ export default util.createRule({ node: reportingNode, messageId, data: { - type: anyType === ESLintUtils.AnyType.Any ? 'any' : 'any[]', + type: anyType === util.AnyType.Any ? 'any' : 'any[]', }, }); } diff --git a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts index 5a6114de5f3..0aedd20cbb2 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts @@ -1,6 +1,6 @@ /* eslint-disable no-fallthrough */ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -294,16 +294,13 @@ export default util.createRule({ return { 'Program:exit'(program: TSESTree.Program): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(program); - const sourceFile = ESLintUtils.getSourceFileOfNode(tsNode); + const sourceFile = util.getSourceFileOfNode(tsNode); const diagnostics = tsProgram.getSemanticDiagnostics(sourceFile); diagnostics.forEach(diag => { if (isUnusedDiagnostic(diag.code)) { if (diag.start !== undefined) { - const node = ESLintUtils.getTokenAtPosition( - sourceFile, - diag.start, - ); + const node = util.getTokenAtPosition(sourceFile, diag.start); const parent = node.parent; if (isIdentifier(node)) { handleIdentifier(node); diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index 9137ce51de0..13a6021c806 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -2,11 +2,15 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, parseRegExpLiteral } from 'regexpp'; import * as ts from 'typescript'; -import { createRule, getParserServices, getStaticValue } from '../util'; +import { + createRule, + getParserServices, + getStaticValue, + getConstrainedTypeAtLocation, +} from '../util'; export default createRule({ name: 'prefer-includes', @@ -213,7 +217,7 @@ export default createRule({ //check the argument type of test methods const argument = callNode.arguments[0]; const tsNode = services.esTreeNodeToTSNodeMap.get(argument); - const type = ESLintUtils.getConstrainedTypeAtLocation(types, tsNode); + const type = getConstrainedTypeAtLocation(types, tsNode); const includesMethodDecl = type .getProperty('includes') diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index 6816e9030b2..fa6c1bb4e21 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -3,7 +3,6 @@ import { AST_TOKEN_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -67,9 +66,7 @@ export default util.createRule({ ): void { const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); const type = checker.getTypeAtLocation(tsNode.left); - const isNullish = ESLintUtils.isNullableType(type, { - allowUndefined: true, - }); + const isNullish = util.isNullableType(type, { allowUndefined: true }); if (!isNullish) { return; } diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 0bc9f7dde2c..56ab8265a9a 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -1,10 +1,10 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; +import { typeIsOrHasBaseType } from '../util'; import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; type MessageIds = 'preferReadonly'; @@ -321,7 +321,7 @@ class ClassScope { const modifierType = this.checker.getTypeAtLocation(node.expression); if ( !modifierType.getSymbol() || - !ESLintUtils.typeIsOrHasBaseType(modifierType, this.classType) + !typeIsOrHasBaseType(modifierType, this.classType) ) { return; } 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 fa883a2e8bd..3b1af79ac6e 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,6 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -68,7 +67,7 @@ export default util.createRule({ // Get the symbol of the `reduce` method. const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( + const calleeObjType = util.getConstrainedTypeAtLocation( checker, tsNode, ); diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index 90a2af78e32..636fe2b3825 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -1,12 +1,12 @@ import { AST_NODE_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { createRule, getParserServices, getStaticValue, + getTypeName, getWrappingFixer, } from '../util'; @@ -44,7 +44,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; + return getTypeName(typeChecker, objectType) === 'string'; } /** @@ -55,7 +55,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( parserServices.esTreeNodeToTSNodeMap.get(node), ); - return ESLintUtils.getTypeName(typeChecker, objectType) === 'RegExp'; + return getTypeName(typeChecker, objectType) === 'RegExp'; } return { diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index 986f7279b45..f4697b7c01d 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import { AST as RegExpAST, RegExpParser } from 'regexpp'; import { @@ -10,6 +9,7 @@ import { getParserServices, getPropertyName, getStaticValue, + getTypeName, isNotClosingParenToken, nullThrows, NullThrowsReasons, @@ -53,7 +53,7 @@ export default createRule({ const objectType = typeChecker.getTypeAtLocation( service.esTreeNodeToTSNodeMap.get(node), ); - return ESLintUtils.getTypeName(typeChecker, objectType) === 'string'; + return getTypeName(typeChecker, objectType) === 'string'; } /** diff --git a/packages/eslint-plugin/src/rules/promise-function-async.ts b/packages/eslint-plugin/src/rules/promise-function-async.ts index d96d4b05008..68b1d42567c 100644 --- a/packages/eslint-plugin/src/rules/promise-function-async.ts +++ b/packages/eslint-plugin/src/rules/promise-function-async.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -111,7 +110,7 @@ export default util.createRule({ const returnType = checker.getReturnTypeOfSignature(signatures[0]); if ( - !ESLintUtils.containsAllTypesByName( + !util.containsAllTypesByName( returnType, allowAny!, allAllowedPromiseNames, @@ -137,10 +136,7 @@ export default util.createRule({ } if ( - ESLintUtils.isTypeFlagSet( - returnType, - ts.TypeFlags.Any | ts.TypeFlags.Unknown, - ) + util.isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown) ) { // Report without auto fixer because the return type is unknown return context.report({ 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 0fa4fae7e12..6e0c49f31a8 100644 --- a/packages/eslint-plugin/src/rules/require-array-sort-compare.ts +++ b/packages/eslint-plugin/src/rules/require-array-sort-compare.ts @@ -1,4 +1,4 @@ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export type Options = [ @@ -55,7 +55,7 @@ export default util.createRule({ if (checker.isArrayType(type) || checker.isTupleType(type)) { const typeArgs = checker.getTypeArguments(type); return typeArgs.every( - arg => ESLintUtils.getTypeName(checker, arg) === 'string', + arg => util.getTypeName(checker, arg) === 'string', ); } return false; @@ -66,7 +66,7 @@ export default util.createRule({ callee: TSESTree.MemberExpression, ): void { const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); - const calleeObjType = ESLintUtils.getConstrainedTypeAtLocation( + const calleeObjType = util.getConstrainedTypeAtLocation( checker, tsNode, ); @@ -75,9 +75,7 @@ export default util.createRule({ return; } - if ( - ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker) - ) { + if (util.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) { context.report({ node: callee.parent!, messageId: 'requireCompare' }); } }, diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index fe40dd81068..0f3b07e9fb2 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -1,4 +1,4 @@ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -59,7 +59,7 @@ export default util.createRule({ } if ( type.isStringLiteral() || - ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) + util.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral) ) { return 'string'; } @@ -96,10 +96,7 @@ export default util.createRule({ */ function getNodeType(node: TSESTree.Expression): BaseLiteral { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( - typeChecker, - tsNode, - ); + const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); return getBaseTypeOfLiteralType(type); } diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index e969d559219..a4756266ffc 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -1,7 +1,6 @@ import { TSESTree, AST_NODE_TYPES, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -52,13 +51,13 @@ export default util.createRule({ const typeChecker = service.program.getTypeChecker(); function isUnderlyingTypePrimitive(type: ts.Type): boolean { - if (ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { + if (util.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { return true; } if ( options.allowNumber && - ESLintUtils.isTypeFlagSet( + util.isTypeFlagSet( type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike, ) @@ -68,21 +67,18 @@ export default util.createRule({ if ( options.allowBoolean && - ESLintUtils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) + util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike) ) { return true; } - if (options.allowAny && ESLintUtils.isTypeAnyType(type)) { + if (options.allowAny && util.isTypeAnyType(type)) { return true; } if ( options.allowNullish && - ESLintUtils.isTypeFlagSet( - type, - ts.TypeFlags.Null | ts.TypeFlags.Undefined, - ) + util.isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined) ) { return true; } @@ -98,7 +94,7 @@ export default util.createRule({ } for (const expression of node.expressions) { - const expressionType = ESLintUtils.getConstrainedTypeAtLocation( + const expressionType = util.getConstrainedTypeAtLocation( typeChecker, service.esTreeNodeToTSNodeMap.get(expression), ); diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index ad7a7ba8a15..85a2eebe1f5 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, TSESLint, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -173,7 +172,7 @@ export default util.createRule({ if (isAwait && !isThenable) { // any/unknown could be thenable; do not auto-fix const useAutoFix = !( - ESLintUtils.isTypeAnyType(type) || ESLintUtils.isTypeUnknownType(type) + util.isTypeAnyType(type) || util.isTypeUnknownType(type) ); const fix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix | null => removeAwait(fixer, node); diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index 55d3f89d647..87796f9f427 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -2,7 +2,6 @@ import { AST_NODE_TYPES, ParserServices, TSESTree, - ESLintUtils, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -226,10 +225,7 @@ export default util.createRule({ } const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); - const type = ESLintUtils.getConstrainedTypeAtLocation( - typeChecker, - tsNode, - ); + const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); const types = inspectVariantTypes(tsutils.unionTypeParts(type)); const is = (...wantedTypes: readonly VariantType[]): boolean => @@ -794,9 +790,7 @@ export default util.createRule({ if ( types.some( - type => - ESLintUtils.isTypeAnyType(type) || - ESLintUtils.isTypeUnknownType(type), + type => util.isTypeAnyType(type) || util.isTypeUnknownType(type), ) ) { variantTypes.add('any'); @@ -832,12 +826,9 @@ function isArrayLengthExpression( return false; } const objectTsNode = parserServices.esTreeNodeToTSNodeMap.get(node.object); - const objectType = ESLintUtils.getConstrainedTypeAtLocation( + const objectType = util.getConstrainedTypeAtLocation( typeChecker, objectTsNode, ); - return ESLintUtils.isTypeArrayTypeOrUnionOfArrayTypes( - objectType, - typeChecker, - ); + return util.isTypeArrayTypeOrUnionOfArrayTypes(objectType, typeChecker); } diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index cd86d2ced8a..8881473da05 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -1,11 +1,8 @@ -import { - TSESLint, - TSESTree, - ESLintUtils, -} from '@typescript-eslint/experimental-utils'; +import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import { createRule, + getConstrainedTypeAtLocation, getParserServices, isClosingBraceToken, isOpeningBraceToken, @@ -40,7 +37,7 @@ export default createRule({ function getNodeType(node: TSESTree.Node): ts.Type { const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return ESLintUtils.getConstrainedTypeAtLocation(checker, tsNode); + return getConstrainedTypeAtLocation(checker, tsNode); } function fixSwitch( From 0a7893e668112ed9962b03e6618f55ab9fbee869 Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Tue, 1 Jun 2021 18:35:05 +1000 Subject: [PATCH 09/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts index d42f91eeb59..aecaaabbfb4 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts @@ -1,8 +1,9 @@ import * as ts from 'typescript'; -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'path'; import { getFixturesRootDir } from '../RuleTester'; +import { isUnsafeAssignment } from '../../src/util'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -37,7 +38,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, From 13fdf564fde435b9186a951b861776ee0db0028c Mon Sep 17 00:00:00 2001 From: detljh Date: Mon, 7 Jun 2021 17:25:55 +1000 Subject: [PATCH 10/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- .../tests/eslint-utils}/isUnsafeAssignment.test.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) rename packages/{eslint-plugin/tests/util => experimental-utils/tests/eslint-utils}/isUnsafeAssignment.test.ts (96%) diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts similarity index 96% rename from packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts rename to packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts index aecaaabbfb4..91ad8984bd3 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts @@ -1,9 +1,8 @@ import * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; +import { getFixturesRootDir } from '@typescript-eslint/eslint-plugin/tests/RuleTester'; import path from 'path'; -import { getFixturesRootDir } from '../RuleTester'; -import { isUnsafeAssignment } from '../../src/util'; +import { ESLintUtils, TSESTree } from '../../src'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -38,7 +37,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, From 8fb132b939ff2d6a193388579977cfd3f5dbed02 Mon Sep 17 00:00:00 2001 From: detljh Date: Fri, 18 Jun 2021 13:34:40 +1000 Subject: [PATCH 11/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils --- .../eslint-utils/isUnsafeAssignment.test.ts | 54 +++++++++++++------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts index 91ad8984bd3..52180e6b973 100644 --- a/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts +++ b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts @@ -4,7 +4,7 @@ import { getFixturesRootDir } from '@typescript-eslint/eslint-plugin/tests/RuleT import path from 'path'; import { ESLintUtils, TSESTree } from '../../src'; -describe('isUnsafeAssignment', () => { +describe('ESLintUtils.isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); function getTypes(code: string): { @@ -55,7 +55,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'any', 'string', @@ -68,7 +68,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -81,7 +81,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Map', 'Map', @@ -94,7 +94,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -107,7 +107,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set>>', 'Set>>', @@ -121,13 +121,17 @@ describe('isUnsafeAssignment', () => { 'const test: string = "";', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any to a any', () => { const { sender, receiver, checker } = getTypes('const test: any = "";'); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any', () => { @@ -135,7 +139,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (multiple generics)', () => { @@ -143,7 +149,9 @@ describe('isUnsafeAssignment', () => { 'const test: Map = new Map();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any[] in a generic position to a non-any[]', () => { @@ -151,7 +159,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (nested)', () => { @@ -159,7 +169,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a any (nested)', () => { @@ -167,7 +179,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any to a unknown', () => { @@ -175,7 +189,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown = [] as any;', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any[] in a generic position to a unknown[]', () => { @@ -183,7 +199,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown[] = [] as any[]', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any in a generic position to a unknown (nested)', () => { @@ -191,7 +209,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); // https://github.com/typescript-eslint/typescript-eslint/issues/2109 @@ -201,7 +221,7 @@ describe('isUnsafeAssignment', () => { ); expect( - isUnsafeAssignment(sender, receiver, checker, senderNode), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, senderNode), ).toBeFalsy(); }); }); From 5ece2d90b55ed08c630acaab054d9021f9bfaa44 Mon Sep 17 00:00:00 2001 From: Lisa Nguyen Date: Mon, 26 Apr 2021 14:29:34 +1000 Subject: [PATCH 12/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils package --- packages/eslint-plugin/src/util/index.ts | 2 +- .../src/eslint-utils/index.ts | 1 + .../src/eslint-utils}/types.ts | 2 +- .../eslint-utils}/isUnsafeAssignment.test.ts | 59 ++++++++++++------- .../typings/typescript.d.ts | 33 +++++++++++ 5 files changed, 75 insertions(+), 22 deletions(-) rename packages/{eslint-plugin/src/util => experimental-utils/src/eslint-utils}/types.ts (99%) rename packages/{eslint-plugin/tests/util => experimental-utils/tests/eslint-utils}/isUnsafeAssignment.test.ts (74%) create mode 100644 packages/experimental-utils/typings/typescript.d.ts diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 4c028489523..4842e84facd 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -12,7 +12,7 @@ export * from './nullThrows'; export * from './objectIterators'; export * from './propertyTypes'; export * from './requiresQuoting'; -export * from './types'; +export * from '@typescript-eslint/experimental-utils/dist/eslint-utils/types'; // this is done for convenience - saves migrating all of the old rules const { applyDefault, deepMerge, isObjectNotArray, getParserServices } = diff --git a/packages/experimental-utils/src/eslint-utils/index.ts b/packages/experimental-utils/src/eslint-utils/index.ts index bbbe8df2709..2381db1d373 100644 --- a/packages/experimental-utils/src/eslint-utils/index.ts +++ b/packages/experimental-utils/src/eslint-utils/index.ts @@ -5,3 +5,4 @@ export * from './InferTypesFromRule'; export * from './RuleCreator'; export * from './RuleTester'; export * from './deepMerge'; +export * from './types'; diff --git a/packages/eslint-plugin/src/util/types.ts b/packages/experimental-utils/src/eslint-utils/types.ts similarity index 99% rename from packages/eslint-plugin/src/util/types.ts rename to packages/experimental-utils/src/eslint-utils/types.ts index 089620e702a..5da17a5e413 100644 --- a/packages/eslint-plugin/src/util/types.ts +++ b/packages/experimental-utils/src/eslint-utils/types.ts @@ -19,7 +19,7 @@ import { } from 'tsutils'; import * as ts from 'typescript'; -const log = debug('typescript-eslint:eslint-plugin:utils:types'); +const log = debug('typescript-eslint:experimental-utils:eslint-utils:types'); /** * Checks if the given type is either an array type, diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts similarity index 74% rename from packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts rename to packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts index 1d4946a964d..709fc91c11b 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts @@ -1,9 +1,8 @@ import * as ts from 'typescript'; -import { TSESTree } from '@typescript-eslint/experimental-utils'; import { parseForESLint } from '@typescript-eslint/parser'; +import { getFixturesRootDir } from '@typescript-eslint/eslint-plugin/tests/RuleTester'; import path from 'path'; -import { getFixturesRootDir } from '../RuleTester'; -import { isUnsafeAssignment } from '../../src/util/types'; +import { ESLintUtils, TSESTree } from '../../src'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -38,7 +37,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, @@ -56,7 +55,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'any', 'string', @@ -69,7 +68,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -82,7 +81,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Map', 'Map', @@ -95,7 +94,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -108,7 +107,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - isUnsafeAssignment(sender, receiver, checker, null), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set>>', 'Set>>', @@ -122,13 +121,17 @@ describe('isUnsafeAssignment', () => { 'const test: string = "";', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any to a any', () => { const { sender, receiver, checker } = getTypes('const test: any = "";'); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any', () => { @@ -136,7 +139,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (multiple generics)', () => { @@ -144,7 +149,9 @@ describe('isUnsafeAssignment', () => { 'const test: Map = new Map();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any[] in a generic position to a non-any[]', () => { @@ -152,7 +159,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a non-any (nested)', () => { @@ -160,7 +169,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('non-any in a generic position to a any (nested)', () => { @@ -168,7 +179,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any to a unknown', () => { @@ -176,7 +189,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown = [] as any;', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any[] in a generic position to a unknown[]', () => { @@ -184,7 +199,9 @@ describe('isUnsafeAssignment', () => { 'const test: unknown[] = [] as any[]', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); it('any in a generic position to a unknown (nested)', () => { @@ -192,7 +209,9 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); + expect( + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + ).toBeFalsy(); }); // https://github.com/typescript-eslint/typescript-eslint/issues/2109 @@ -202,7 +221,7 @@ describe('isUnsafeAssignment', () => { ); expect( - isUnsafeAssignment(sender, receiver, checker, senderNode), + ESLintUtils.isUnsafeAssignment(sender, receiver, checker, senderNode), ).toBeFalsy(); }); }); diff --git a/packages/experimental-utils/typings/typescript.d.ts b/packages/experimental-utils/typings/typescript.d.ts new file mode 100644 index 00000000000..73304155ee7 --- /dev/null +++ b/packages/experimental-utils/typings/typescript.d.ts @@ -0,0 +1,33 @@ +import 'typescript'; + +declare module 'typescript' { + interface TypeChecker { + // internal TS APIs + + /** + * @returns `true` if the given type is an array type: + * - `Array` + * - `ReadonlyArray` + * - `foo[]` + * - `readonly foo[]` + */ + isArrayType(type: Type): type is TypeReference; + /** + * @returns `true` if the given type is a tuple type: + * - `[foo]` + * - `readonly [foo]` + */ + isTupleType(type: Type): type is TupleTypeReference; + /** + * Return the type of the given property in the given type, or undefined if no such property exists + */ + getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; + } + + interface Type { + /** + * If the type is `any`, and this is set to "error", then TS was unable to resolve the type + */ + intrinsicName?: string; + } +} From 2853bde8da753ab7c36aa288c26f9c4807fadf22 Mon Sep 17 00:00:00 2001 From: detljh Date: Wed, 14 Jul 2021 14:50:12 +1000 Subject: [PATCH 13/15] feat(experimental-utils): moved types eslint-plugin util to experimental-utils --- packages/experimental-utils/package.json | 5 +- .../src/eslint-utils/types.ts | 5 +- .../eslint-utils/isUnsafeAssignment.test.ts | 57 +++++++------------ 3 files changed, 24 insertions(+), 43 deletions(-) diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index 27e3a328268..214a1f53863 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -43,10 +43,13 @@ "@typescript-eslint/scope-manager": "4.28.3", "@typescript-eslint/types": "4.28.3", "@typescript-eslint/typescript-estree": "4.28.3", + "debug": "^4.3.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "tsutils": "^3.21.0" }, "peerDependencies": { + "@typescript-eslint/parser": "^4.0.0", "eslint": "*" }, "devDependencies": { diff --git a/packages/experimental-utils/src/eslint-utils/types.ts b/packages/experimental-utils/src/eslint-utils/types.ts index 5da17a5e413..fc1295348ff 100644 --- a/packages/experimental-utils/src/eslint-utils/types.ts +++ b/packages/experimental-utils/src/eslint-utils/types.ts @@ -1,7 +1,4 @@ -import { - AST_NODE_TYPES, - TSESTree, -} from '@typescript-eslint/experimental-utils'; +import { AST_NODE_TYPES, TSESTree } from '../index'; import debug from 'debug'; import { isCallExpression, diff --git a/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts index 709fc91c11b..7ec151091e0 100644 --- a/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts +++ b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts @@ -2,7 +2,8 @@ import * as ts from 'typescript'; import { parseForESLint } from '@typescript-eslint/parser'; import { getFixturesRootDir } from '@typescript-eslint/eslint-plugin/tests/RuleTester'; import path from 'path'; -import { ESLintUtils, TSESTree } from '../../src'; +import { isUnsafeAssignment } from '../../src/eslint-utils/types'; +import { TSESTree } from '../../src'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); @@ -37,7 +38,7 @@ describe('isUnsafeAssignment', () => { describe('unsafe', () => { function expectTypesAre( - result: ReturnType, + result: ReturnType, checker: ts.TypeChecker, senderStr: string, receiverStr: string, @@ -55,7 +56,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + isUnsafeAssignment(sender, receiver, checker, null), checker, 'any', 'string', @@ -68,7 +69,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -81,7 +82,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + isUnsafeAssignment(sender, receiver, checker, null), checker, 'Map', 'Map', @@ -94,7 +95,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set', 'Set', @@ -107,7 +108,7 @@ describe('isUnsafeAssignment', () => { ); expectTypesAre( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), + isUnsafeAssignment(sender, receiver, checker, null), checker, 'Set>>', 'Set>>', @@ -121,17 +122,13 @@ describe('isUnsafeAssignment', () => { 'const test: string = "";', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('non-any to a any', () => { const { sender, receiver, checker } = getTypes('const test: any = "";'); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('non-any in a generic position to a non-any', () => { @@ -139,9 +136,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('non-any in a generic position to a non-any (multiple generics)', () => { @@ -149,9 +144,7 @@ describe('isUnsafeAssignment', () => { 'const test: Map = new Map();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('non-any[] in a generic position to a non-any[]', () => { @@ -159,9 +152,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set = new Set();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('non-any in a generic position to a non-any (nested)', () => { @@ -169,9 +160,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('non-any in a generic position to a any (nested)', () => { @@ -179,9 +168,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('any to a unknown', () => { @@ -189,9 +176,7 @@ describe('isUnsafeAssignment', () => { 'const test: unknown = [] as any;', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('any[] in a generic position to a unknown[]', () => { @@ -199,9 +184,7 @@ describe('isUnsafeAssignment', () => { 'const test: unknown[] = [] as any[]', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); it('any in a generic position to a unknown (nested)', () => { @@ -209,9 +192,7 @@ describe('isUnsafeAssignment', () => { 'const test: Set>> = new Set>>();', ); - expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, null), - ).toBeFalsy(); + expect(isUnsafeAssignment(sender, receiver, checker, null)).toBeFalsy(); }); // https://github.com/typescript-eslint/typescript-eslint/issues/2109 @@ -221,7 +202,7 @@ describe('isUnsafeAssignment', () => { ); expect( - ESLintUtils.isUnsafeAssignment(sender, receiver, checker, senderNode), + isUnsafeAssignment(sender, receiver, checker, senderNode), ).toBeFalsy(); }); }); From e2e2903c76c5733c5177f1858c2c7cb8b8d6f295 Mon Sep 17 00:00:00 2001 From: Armano Date: Fri, 17 Dec 2021 18:15:11 +0100 Subject: [PATCH 14/15] fix: remove typescript-eslint/parser to dev dep --- packages/experimental-utils/package.json | 4 ++-- .../tests/eslint-utils/isUnsafeAssignment.test.ts | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index cc45c246777..16d80e973a0 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -49,11 +49,11 @@ "tsutils": "^3.21.0" }, "peerDependencies": { - "@typescript-eslint/parser": "^5.7.0", "eslint": "*" }, "devDependencies": { - "typescript": "*" + "typescript": "*", + "@typescript-eslint/parser": "^5.7.0" }, "funding": { "type": "opencollective", diff --git a/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts index 7ec151091e0..2470f2a8614 100644 --- a/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts +++ b/packages/experimental-utils/tests/eslint-utils/isUnsafeAssignment.test.ts @@ -1,9 +1,13 @@ import * as ts from 'typescript'; import { parseForESLint } from '@typescript-eslint/parser'; -import { getFixturesRootDir } from '@typescript-eslint/eslint-plugin/tests/RuleTester'; import path from 'path'; -import { isUnsafeAssignment } from '../../src/eslint-utils/types'; -import { TSESTree } from '../../src'; +import { TSESTree, ESLintUtils } from '../../src'; + +import isUnsafeAssignment = ESLintUtils.isUnsafeAssignment; + +function getFixturesRootDir(): string { + return path.join(__dirname, '../../../eslint-plugin/tests/fixtures'); +} describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); From 09d5ee90719cf96f33be8c3e03a1a9adedad5c2a Mon Sep 17 00:00:00 2001 From: Armano Date: Tue, 21 Dec 2021 22:22:26 +0100 Subject: [PATCH 15/15] fix(eslint-plugin): correct circular dependency --- packages/eslint-plugin/src/util/index.ts | 1 + packages/experimental-utils/src/eslint-utils/types.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 4842e84facd..454837f5baa 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -12,6 +12,7 @@ export * from './nullThrows'; export * from './objectIterators'; export * from './propertyTypes'; export * from './requiresQuoting'; +// TODO: remove in next major release export * from '@typescript-eslint/experimental-utils/dist/eslint-utils/types'; // this is done for convenience - saves migrating all of the old rules diff --git a/packages/experimental-utils/src/eslint-utils/types.ts b/packages/experimental-utils/src/eslint-utils/types.ts index fc1295348ff..dbe0c1a5825 100644 --- a/packages/experimental-utils/src/eslint-utils/types.ts +++ b/packages/experimental-utils/src/eslint-utils/types.ts @@ -1,4 +1,4 @@ -import { AST_NODE_TYPES, TSESTree } from '../index'; +import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/types'; import debug from 'debug'; import { isCallExpression,