diff --git a/src/rules/prefer-to-have-length.ts b/src/rules/prefer-to-have-length.ts index c448ff9b3..5d78550f3 100644 --- a/src/rules/prefer-to-have-length.ts +++ b/src/rules/prefer-to-have-length.ts @@ -1,9 +1,9 @@ import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import { createRule, - isAccessorNode, isExpectCall, isParsedEqualityMatcherCall, + isSupportedAccessor, parseExpectCall, } from './utils'; @@ -42,7 +42,7 @@ export default createRule({ !isParsedEqualityMatcherCall(matcher) || !argument || argument.type !== AST_NODE_TYPES.MemberExpression || - !isAccessorNode(argument.property, 'length') || + !isSupportedAccessor(argument.property, 'length') || argument.property.type !== AST_NODE_TYPES.Identifier ) { return; diff --git a/src/rules/utils.ts b/src/rules/utils.ts index cbc122379..ab7efb90a 100644 --- a/src/rules/utils.ts +++ b/src/rules/utils.ts @@ -162,12 +162,44 @@ const isIdentifier = ( node.type === AST_NODE_TYPES.Identifier && (name === undefined || node.name === name); +/** + * Checks if the given `node` is a "supported accessor". + * + * This means that it's a node can be used to access properties, + * and who's "value" can be statically determined. + * + * `MemberExpression` nodes most commonly contain accessors, + * but it's possible for other nodes to contain them. + * + * If a `value` is provided & the `node` is an `AccessorNode`, + * the `value` will be compared to that of the `AccessorNode`. + * + * Note that `value` here refers to the normalised value. + * The property that holds the value is not always called `name`. + * + * @param {Node} node + * @param {V?} value + * + * @return {node is AccessorNode} + * + * @template V + */ export const isSupportedAccessor = ( node: TSESTree.Node, value?: V, ): node is AccessorNode => isIdentifier(node, value) || isStringNode(node, value); +/** + * Gets the value of the given `AccessorNode`, + * account for the different node types. + * + * @param {AccessorNode} accessor + * + * @return {S} + * + * @template S + */ export const getAccessorValue = ( accessor: AccessorNode, ): S => @@ -175,22 +207,6 @@ export const getAccessorValue = ( ? accessor.name : getStringValue(accessor); -/** - * Checks if the given `node` is an `AccessorExpression` with the specific `value`. - * - * @param {Node} node - * @param {V} accessor - * - * @return {node is SpecificAccessorExpression} - * - * @template V - */ -export const isAccessorNode = ( - node: TSESTree.Node, - accessor: V, -): node is AccessorNode => - isIdentifier(node, accessor) || isStringNode(node, accessor); - export interface ValidExpectCall< Argument extends TSESTree.Expression = TSESTree.Expression > extends ExpectCall { @@ -215,7 +231,7 @@ type AccessorNode = type ExpectAccessor = AccessorNode<'expect'>; export const isExpectAccessor = (node: TSESTree.Node): node is ExpectAccessor => - isAccessorNode(node, 'expect'); + isSupportedAccessor(node, 'expect'); export interface ExpectCall extends TSESTree.CallExpression { callee: AccessorNode<'expect'>;