From a242cfa31024d8242093f394573d03677261ac47 Mon Sep 17 00:00:00 2001 From: Jason Weinzierl Date: Wed, 13 Nov 2024 19:42:33 -0600 Subject: [PATCH 1/2] refactor: remove getType and typeChecker from getTypeServices --- src/etc/get-type-services.ts | 16 +++++----------- src/rules/no-cyclic-action.ts | 11 ++++++----- src/rules/no-unbound-methods.ts | 8 ++++---- src/rules/no-unsafe-subject-next.ts | 12 +++++++----- src/rules/throw-error.ts | 6 +++--- 5 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/etc/get-type-services.ts b/src/etc/get-type-services.ts index 75f814c8..f42cac58 100644 --- a/src/etc/get-type-services.ts +++ b/src/etc/get-type-services.ts @@ -18,7 +18,7 @@ export function getTypeServices< name: string | RegExp, qualified?: { name: RegExp }, ): boolean => { - const type = getType(node); + const type = getTypeAtLocation(node); return tsutilsEtcCouldBeType( type, name, @@ -56,10 +56,6 @@ export function getTypeServices< ); }; - const getType = (node: TSESTree.Node): ts.Type => { - return getTypeAtLocation(node); - }; - return { couldBeBehaviorSubject: (node: TSESTree.Node) => couldBeType(node, 'BehaviorSubject'), @@ -68,7 +64,7 @@ export function getTypeServices< if (isArrowFunctionExpression(node) || isFunctionDeclaration(node)) { return true; } - return couldBeFunction(getType(node)); + return couldBeFunction(getTypeAtLocation(node)); }, couldBeMonoTypeOperatorFunction: (node: TSESTree.Node) => couldBeType(node, 'MonoTypeOperatorFunction'), @@ -79,10 +75,8 @@ export function getTypeServices< couldReturnObservable: (node: TSESTree.Node) => couldReturnType(node, 'Observable'), couldReturnType, - getType, - isAny: (node: TSESTree.Node) => tsutils.isIntrinsicAnyType(getType(node)), - isReferenceType: (node: TSESTree.Node) => tsutils.isTypeReference(getType(node)), - isUnknown: (node: TSESTree.Node) => tsutils.isIntrinsicUnknownType(getType(node)), - typeChecker, + isAny: (node: TSESTree.Node) => tsutils.isIntrinsicAnyType(getTypeAtLocation(node)), + isReferenceType: (node: TSESTree.Node) => tsutils.isTypeReference(getTypeAtLocation(node)), + isUnknown: (node: TSESTree.Node) => tsutils.isIntrinsicUnknownType(getTypeAtLocation(node)), }; } diff --git a/src/rules/no-cyclic-action.ts b/src/rules/no-cyclic-action.ts index 5df88fa7..6e85e3e5 100644 --- a/src/rules/no-cyclic-action.ts +++ b/src/rules/no-cyclic-action.ts @@ -1,8 +1,8 @@ -import { TSESTree as es } from '@typescript-eslint/utils'; +import { TSESTree as es, ESLintUtils } from '@typescript-eslint/utils'; import { stripIndent } from 'common-tags'; import ts from 'typescript'; import { defaultObservable } from '../constants'; -import { getTypeServices, isCallExpression, isIdentifier } from '../etc'; +import { isCallExpression, isIdentifier } from '../etc'; import { ruleCreator } from '../utils'; function isTypeReference(type: ts.Type): type is ts.TypeReference { @@ -44,7 +44,8 @@ export const noCyclicActionRule = ruleCreator({ const { observable = defaultObservable } = config; const observableRegExp = new RegExp(observable); - const { getType, typeChecker } = getTypeServices(context); + const { getTypeAtLocation, program } = ESLintUtils.getParserServices(context); + const typeChecker = program.getTypeChecker(); function checkNode(pipeCallExpression: es.CallExpression) { const operatorCallExpression = pipeCallExpression.arguments.find( @@ -56,7 +57,7 @@ export const noCyclicActionRule = ruleCreator({ if (!operatorCallExpression) { return; } - const operatorType = getType(operatorCallExpression); + const operatorType = getTypeAtLocation(operatorCallExpression); const [signature] = typeChecker.getSignaturesOfType( operatorType, ts.SignatureKind.Call, @@ -75,7 +76,7 @@ export const noCyclicActionRule = ruleCreator({ return; } - const pipeType = getType(pipeCallExpression); + const pipeType = getTypeAtLocation(pipeCallExpression); if (!isTypeReference(pipeType)) { return; } diff --git a/src/rules/no-unbound-methods.ts b/src/rules/no-unbound-methods.ts index acf378c6..706f91a4 100644 --- a/src/rules/no-unbound-methods.ts +++ b/src/rules/no-unbound-methods.ts @@ -1,4 +1,4 @@ -import { TSESTree as es } from '@typescript-eslint/utils'; +import { TSESTree as es, ESLintUtils } from '@typescript-eslint/utils'; import { getTypeServices, isCallExpression, @@ -21,13 +21,13 @@ export const noUnboundMethodsRule = ruleCreator({ }, name: 'no-unbound-methods', create: (context) => { - const { couldBeObservable, couldBeSubscription, getType } - = getTypeServices(context); + const { getTypeAtLocation } = ESLintUtils.getParserServices(context); + const { couldBeObservable, couldBeSubscription } = getTypeServices(context); const nodeMap = new WeakMap(); function mapArguments(node: es.CallExpression | es.NewExpression) { node.arguments.filter(isMemberExpression).forEach((arg) => { - const argType = getType(arg); + const argType = getTypeAtLocation(arg); if (argType.getCallSignatures().length > 0) { nodeMap.set(arg); } diff --git a/src/rules/no-unsafe-subject-next.ts b/src/rules/no-unsafe-subject-next.ts index 9745179c..f5fae2af 100644 --- a/src/rules/no-unsafe-subject-next.ts +++ b/src/rules/no-unsafe-subject-next.ts @@ -1,10 +1,10 @@ -import { TSESTree as es } from '@typescript-eslint/utils'; +import { TSESTree as es, ESLintUtils } from '@typescript-eslint/utils'; import * as tsutils from 'ts-api-utils'; import ts from 'typescript'; import { couldBeType, - getTypeServices, - isMemberExpression } from '../etc'; + isMemberExpression, +} from '../etc'; import { ruleCreator } from '../utils'; export const noUnsafeSubjectNext = ruleCreator({ @@ -23,13 +23,15 @@ export const noUnsafeSubjectNext = ruleCreator({ }, name: 'no-unsafe-subject-next', create: (context) => { - const { getType, typeChecker } = getTypeServices(context); + const { getTypeAtLocation, program } = ESLintUtils.getParserServices(context); + const typeChecker = program.getTypeChecker(); + return { [`CallExpression[callee.property.name='next']`]: ( node: es.CallExpression, ) => { if (node.arguments.length === 0 && isMemberExpression(node.callee)) { - const type = getType(node.callee.object); + const type = getTypeAtLocation(node.callee.object); if (tsutils.isTypeReference(type) && couldBeType(type, 'Subject')) { const [typeArg] = typeChecker.getTypeArguments(type); if (tsutils.isTypeFlagSet(typeArg, ts.TypeFlags.Any)) { diff --git a/src/rules/throw-error.ts b/src/rules/throw-error.ts index 4cd7801f..beb6cfae 100644 --- a/src/rules/throw-error.ts +++ b/src/rules/throw-error.ts @@ -20,11 +20,11 @@ export const throwErrorRule = ruleCreator({ }, name: 'throw-error', create: (context) => { - const { esTreeNodeToTSNodeMap, program } = ESLintUtils.getParserServices(context); - const { couldBeObservable, getType } = getTypeServices(context); + const { esTreeNodeToTSNodeMap, program, getTypeAtLocation } = ESLintUtils.getParserServices(context); + const { couldBeObservable } = getTypeServices(context); function checkNode(node: es.Node) { - let type = getType(node); + let type = getTypeAtLocation(node); if (couldBeFunction(type)) { const tsNode = esTreeNodeToTSNodeMap.get(node); const annotation = (tsNode as ts.ArrowFunction).type; From 5b8a8485024b6512a5e5b390f9ce968a504a9bf5 Mon Sep 17 00:00:00 2001 From: Jason Weinzierl Date: Wed, 13 Nov 2024 19:48:49 -0600 Subject: [PATCH 2/2] refactor: remove unused functions from getTypeServices --- src/etc/get-type-services.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/etc/get-type-services.ts b/src/etc/get-type-services.ts index f42cac58..71cb1db4 100644 --- a/src/etc/get-type-services.ts +++ b/src/etc/get-type-services.ts @@ -1,5 +1,4 @@ import { ESLintUtils, TSESLint, TSESTree } from '@typescript-eslint/utils'; -import * as tsutils from 'ts-api-utils'; import ts from 'typescript'; import { couldBeFunction } from './could-be-function'; import { couldBeType as tsutilsEtcCouldBeType } from './could-be-type'; @@ -59,7 +58,6 @@ export function getTypeServices< return { couldBeBehaviorSubject: (node: TSESTree.Node) => couldBeType(node, 'BehaviorSubject'), - couldBeError: (node: TSESTree.Node) => couldBeType(node, 'Error'), couldBeFunction: (node: TSESTree.Node) => { if (isArrowFunctionExpression(node) || isFunctionDeclaration(node)) { return true; @@ -75,8 +73,5 @@ export function getTypeServices< couldReturnObservable: (node: TSESTree.Node) => couldReturnType(node, 'Observable'), couldReturnType, - isAny: (node: TSESTree.Node) => tsutils.isIntrinsicAnyType(getTypeAtLocation(node)), - isReferenceType: (node: TSESTree.Node) => tsutils.isTypeReference(getTypeAtLocation(node)), - isUnknown: (node: TSESTree.Node) => tsutils.isIntrinsicUnknownType(getTypeAtLocation(node)), }; }