From e68ee36341d7ab7066263d2833c3e7662ca0695c Mon Sep 17 00:00:00 2001 From: thomlom Date: Tue, 17 Nov 2020 09:32:19 +0100 Subject: [PATCH 1/3] refactor(ast-utils): remove isIdentifier --- lib/node-utils.ts | 14 ++++-------- lib/rules/await-async-query.ts | 11 +++++---- lib/rules/await-async-utils.ts | 11 +++++---- lib/rules/await-fire-event.ts | 10 +++++--- lib/rules/no-await-sync-events.ts | 10 +++++--- lib/rules/no-container.ts | 21 +++++++++-------- lib/rules/no-debug.ts | 13 +++++++---- lib/rules/no-multiple-assertions-wait-for.ts | 9 +++++--- lib/rules/no-node-access.ts | 5 ++-- lib/rules/no-promise-in-fire-event.ts | 9 +++++--- lib/rules/no-render-in-setup.ts | 11 +++++---- lib/rules/no-side-effects-wait-for.ts | 9 +++++--- lib/rules/no-wait-for-empty-callback.ts | 14 ++++++------ lib/rules/prefer-explicit-assert.ts | 14 ++++++------ lib/rules/prefer-find-by.ts | 19 +++++++++------- lib/rules/prefer-screen-queries.ts | 24 ++++++++++++-------- lib/rules/prefer-user-event.ts | 14 ++++++------ lib/rules/prefer-wait-for.ts | 11 +++++---- lib/rules/render-result-naming-convention.ts | 15 +++++++----- 19 files changed, 143 insertions(+), 101 deletions(-) diff --git a/lib/node-utils.ts b/lib/node-utils.ts index b187e4e0..c2d3ff04 100644 --- a/lib/node-utils.ts +++ b/lib/node-utils.ts @@ -18,11 +18,6 @@ export function isNewExpression( return node && node.type === 'NewExpression'; } -// TODO: remove this one and use ASTUtils one instead -export function isIdentifier(node: TSESTree.Node): node is TSESTree.Identifier { - return node && node.type === AST_NODE_TYPES.Identifier; -} - export function isMemberExpression( node: TSESTree.Node ): node is TSESTree.MemberExpression { @@ -107,7 +102,7 @@ export function findClosestCallNode( if ( isCallExpression(node) && - isIdentifier(node.callee) && + ASTUtils.isIdentifier(node.callee) && node.callee.name === name ) { return node; @@ -125,7 +120,7 @@ export function isObjectExpression( export function hasThenProperty(node: TSESTree.Node): boolean { return ( isMemberExpression(node) && - isIdentifier(node.property) && + ASTUtils.isIdentifier(node.property) && node.property.name === 'then' ); } @@ -200,9 +195,10 @@ export function isRenderFunction( // as well as `someLib.render` and `someUtils.customRenderFn` return renderFunctions.some((name) => { return ( - (isIdentifier(callNode.callee) && name === callNode.callee.name) || + (ASTUtils.isIdentifier(callNode.callee) && + name === callNode.callee.name) || (isMemberExpression(callNode.callee) && - isIdentifier(callNode.callee.property) && + ASTUtils.isIdentifier(callNode.callee.property) && name === callNode.callee.property.name) ); }); diff --git a/lib/rules/await-async-query.ts b/lib/rules/await-async-query.ts index 10d8d658..730188c2 100644 --- a/lib/rules/await-async-query.ts +++ b/lib/rules/await-async-query.ts @@ -1,8 +1,11 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, LIBRARY_MODULES } from '../utils'; import { isCallExpression, - isIdentifier, isMemberExpression, isAwaited, isPromiseResolved, @@ -23,13 +26,13 @@ function hasClosestExpectResolvesRejects(node: TSESTree.Node): boolean { if ( isCallExpression(node) && - isIdentifier(node.callee) && + ASTUtils.isIdentifier(node.callee) && isMemberExpression(node.parent) && node.callee.name === 'expect' ) { const expectMatcher = node.parent.property; return ( - isIdentifier(expectMatcher) && + ASTUtils.isIdentifier(expectMatcher) && (expectMatcher.name === 'resolves' || expectMatcher.name === 'rejects') ); } else { diff --git a/lib/rules/await-async-utils.ts b/lib/rules/await-async-utils.ts index 04186616..6301bd4e 100644 --- a/lib/rules/await-async-utils.ts +++ b/lib/rules/await-async-utils.ts @@ -1,4 +1,8 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, ASYNC_UTILS, LIBRARY_MODULES } from '../utils'; import { @@ -10,7 +14,6 @@ import { isImportNamespaceSpecifier, isCallExpression, isArrayExpression, - isIdentifier, } from '../node-utils'; export const RULE_NAME = 'await-async-utils'; @@ -23,9 +26,9 @@ const ASYNC_UTILS_REGEXP = new RegExp(`^(${ASYNC_UTILS.join('|')})$`); function isPromiseAll(node: TSESTree.CallExpression) { return ( isMemberExpression(node.callee) && - isIdentifier(node.callee.object) && + ASTUtils.isIdentifier(node.callee.object) && node.callee.object.name === 'Promise' && - isIdentifier(node.callee.property) && + ASTUtils.isIdentifier(node.callee.property) && node.callee.property.name === 'all' ); } diff --git a/lib/rules/await-fire-event.ts b/lib/rules/await-fire-event.ts index 1012e929..a347658d 100644 --- a/lib/rules/await-fire-event.ts +++ b/lib/rules/await-fire-event.ts @@ -1,6 +1,10 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl } from '../utils'; -import { isIdentifier, isAwaited, isPromiseResolved } from '../node-utils'; +import { isAwaited, isPromiseResolved } from '../node-utils'; export const RULE_NAME = 'await-fire-event'; export type MessageIds = 'awaitFireEvent'; @@ -31,7 +35,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ const fireEventMethodNode = memberExpression.property; if ( - isIdentifier(fireEventMethodNode) && + ASTUtils.isIdentifier(fireEventMethodNode) && !isAwaited(node.parent.parent.parent) && !isPromiseResolved(fireEventMethodNode.parent) ) { diff --git a/lib/rules/no-await-sync-events.ts b/lib/rules/no-await-sync-events.ts index ccb57352..e612d952 100644 --- a/lib/rules/no-await-sync-events.ts +++ b/lib/rules/no-await-sync-events.ts @@ -1,6 +1,10 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ASTUtils, + ESLintUtils, + TSESTree, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, SYNC_EVENTS } from '../utils'; -import { isObjectExpression, isProperty, isIdentifier } from '../node-utils'; +import { isObjectExpression, isProperty } from '../node-utils'; export const RULE_NAME = 'no-await-sync-events'; export type MessageIds = 'noAwaitSyncEvents'; type Options = []; @@ -41,7 +45,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ callExpression.arguments[2].properties.some( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && property.key.name === 'delay' ); diff --git a/lib/rules/no-container.ts b/lib/rules/no-container.ts index 89000731..7970ec9c 100644 --- a/lib/rules/no-container.ts +++ b/lib/rules/no-container.ts @@ -1,7 +1,10 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl } from '../utils'; import { - isIdentifier, isMemberExpression, isObjectPattern, isProperty, @@ -54,12 +57,12 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ innerNode: TSESTree.MemberExpression ) { if (isMemberExpression(innerNode)) { - if (isIdentifier(innerNode.object)) { + if (ASTUtils.isIdentifier(innerNode.object)) { const isContainerName = innerNode.object.name === containerName; const isRenderWrapper = innerNode.object.name === renderWrapperName; containerCallsMethod = - isIdentifier(innerNode.property) && + ASTUtils.isIdentifier(innerNode.property) && innerNode.property.name === 'container' && isRenderWrapper; @@ -83,24 +86,24 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ const containerIndex = node.id.properties.findIndex( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && property.key.name === 'container' ); const nodeValue = containerIndex !== -1 && node.id.properties[containerIndex].value; - if (isIdentifier(nodeValue)) { + if (ASTUtils.isIdentifier(nodeValue)) { containerName = nodeValue.name; } else { isObjectPattern(nodeValue) && nodeValue.properties.forEach( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && destructuredContainerPropNames.push(property.key.name) ); } } else { - renderWrapperName = isIdentifier(node.id) && node.id.name; + renderWrapperName = ASTUtils.isIdentifier(node.id) && node.id.name; } } }, @@ -109,7 +112,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ if (isMemberExpression(node.callee)) { showErrorIfChainedContainerMethod(node.callee); } else { - isIdentifier(node.callee) && + ASTUtils.isIdentifier(node.callee) && destructuredContainerPropNames.includes(node.callee.name) && context.report({ node, diff --git a/lib/rules/no-debug.ts b/lib/rules/no-debug.ts index cf512284..e2023e91 100644 --- a/lib/rules/no-debug.ts +++ b/lib/rules/no-debug.ts @@ -1,4 +1,8 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, LIBRARY_MODULES, @@ -7,7 +11,6 @@ import { import { isObjectPattern, isProperty, - isIdentifier, isCallExpression, isLiteral, isMemberExpression, @@ -66,7 +69,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ node.id.properties.some( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && property.key.name === 'debug' ) ) { @@ -102,7 +105,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ declaratorNode.id.properties.some( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && property.key.name === 'screen' ); }, @@ -179,7 +182,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ const parent = ref.identifier.parent; if ( isMemberExpression(parent) && - isIdentifier(parent.property) && + ASTUtils.isIdentifier(parent.property) && parent.property.name === 'debug' && isCallExpression(parent.parent) ) { diff --git a/lib/rules/no-multiple-assertions-wait-for.ts b/lib/rules/no-multiple-assertions-wait-for.ts index 7c095894..99fb11b5 100644 --- a/lib/rules/no-multiple-assertions-wait-for.ts +++ b/lib/rules/no-multiple-assertions-wait-for.ts @@ -1,10 +1,13 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl } from '../utils'; import { isBlockStatement, isMemberExpression, isCallExpression, - isIdentifier, } from '../node-utils'; export const RULE_NAME = 'no-multiple-assertions-wait-for'; @@ -42,7 +45,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ const object: TSESTree.CallExpression = node.expression.callee.object; const expressionName: string = - isIdentifier(object.callee) && object.callee.name; + ASTUtils.isIdentifier(object.callee) && object.callee.name; return expressionName === 'expect'; } else { return false; diff --git a/lib/rules/no-node-access.ts b/lib/rules/no-node-access.ts index 2c6f97e2..9b71ceac 100644 --- a/lib/rules/no-node-access.ts +++ b/lib/rules/no-node-access.ts @@ -1,6 +1,5 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ASTUtils } from '@typescript-eslint/experimental-utils'; import { ALL_RETURNING_NODES } from '../utils'; -import { isIdentifier } from '../node-utils'; import { createTestingLibraryRule } from '../create-testing-library-rule'; export const RULE_NAME = 'no-node-access'; @@ -27,7 +26,7 @@ export default createTestingLibraryRule({ create(context) { function showErrorForNodeAccess(node: TSESTree.MemberExpression) { - isIdentifier(node.property) && + ASTUtils.isIdentifier(node.property) && ALL_RETURNING_NODES.includes(node.property.name) && context.report({ node: node, diff --git a/lib/rules/no-promise-in-fire-event.ts b/lib/rules/no-promise-in-fire-event.ts index d05d0605..c51390a0 100644 --- a/lib/rules/no-promise-in-fire-event.ts +++ b/lib/rules/no-promise-in-fire-event.ts @@ -1,8 +1,11 @@ -import { TSESTree, ESLintUtils } from '@typescript-eslint/experimental-utils'; +import { + TSESTree, + ESLintUtils, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, ASYNC_QUERIES_VARIANTS } from '../utils'; import { isNewExpression, - isIdentifier, isImportSpecifier, isCallExpression, } from '../node-utils'; @@ -52,7 +55,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ .parent as TSESTree.CallExpression; const [element] = callExpression.arguments as TSESTree.Node[]; if (isCallExpression(element) || isNewExpression(element)) { - const methodName = isIdentifier(element.callee) + const methodName = ASTUtils.isIdentifier(element.callee) ? element.callee.name : ((element.callee as TSESTree.MemberExpression) .property as TSESTree.Identifier).name; diff --git a/lib/rules/no-render-in-setup.ts b/lib/rules/no-render-in-setup.ts index ecfce6d4..66728e07 100644 --- a/lib/rules/no-render-in-setup.ts +++ b/lib/rules/no-render-in-setup.ts @@ -1,9 +1,12 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, TESTING_FRAMEWORK_SETUP_HOOKS } from '../utils'; import { isLiteral, isProperty, - isIdentifier, isObjectPattern, isCallExpression, isRenderFunction, @@ -29,7 +32,7 @@ export function findClosestBeforeHook( if ( isCallExpression(node) && - isIdentifier(node.callee) && + ASTUtils.isIdentifier(node.callee) && testingFrameworkSetupHooksToFilter.includes(node.callee.name) ) { return node.callee; @@ -126,7 +129,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ declaratorNode.id.properties.some( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && property.key.name === 'render' ); }, diff --git a/lib/rules/no-side-effects-wait-for.ts b/lib/rules/no-side-effects-wait-for.ts index 9cd31111..d3b55504 100644 --- a/lib/rules/no-side-effects-wait-for.ts +++ b/lib/rules/no-side-effects-wait-for.ts @@ -1,10 +1,13 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, hasTestingLibraryImportModule } from '../utils'; import { isBlockStatement, isMemberExpression, isCallExpression, - isIdentifier, } from '../node-utils'; export const RULE_NAME = 'no-side-effects-wait-for'; @@ -41,7 +44,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ if ( isCallExpression(node.expression) && isMemberExpression(node.expression.callee) && - isIdentifier(node.expression.callee.object) + ASTUtils.isIdentifier(node.expression.callee.object) ) { const object: TSESTree.Identifier = node.expression.callee.object; const identifierName: string = object.name; diff --git a/lib/rules/no-wait-for-empty-callback.ts b/lib/rules/no-wait-for-empty-callback.ts index 6c53b88e..7ff27dd9 100644 --- a/lib/rules/no-wait-for-empty-callback.ts +++ b/lib/rules/no-wait-for-empty-callback.ts @@ -1,10 +1,10 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; -import { getDocsUrl } from '../utils'; import { - isBlockStatement, - isCallExpression, - isIdentifier, -} from '../node-utils'; + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; +import { getDocsUrl } from '../utils'; +import { isBlockStatement, isCallExpression } from '../node-utils'; export const RULE_NAME = 'no-wait-for-empty-callback'; export type MessageIds = 'noWaitForEmptyCallback'; @@ -42,7 +42,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ isBlockStatement(node.body) && node.body.body.length === 0 && isCallExpression(node.parent) && - isIdentifier(node.parent.callee) + ASTUtils.isIdentifier(node.parent.callee) ) { context.report({ node, diff --git a/lib/rules/prefer-explicit-assert.ts b/lib/rules/prefer-explicit-assert.ts index 6b775244..13bb359b 100644 --- a/lib/rules/prefer-explicit-assert.ts +++ b/lib/rules/prefer-explicit-assert.ts @@ -1,15 +1,15 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, ALL_QUERIES_METHODS, PRESENCE_MATCHERS, ABSENCE_MATCHERS, } from '../utils'; -import { - findClosestCallNode, - isIdentifier, - isMemberExpression, -} from '../node-utils'; +import { findClosestCallNode, isMemberExpression } from '../node-utils'; export const RULE_NAME = 'prefer-explicit-assert'; export type MessageIds = @@ -104,7 +104,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ if ( matcher === 'not' && isMemberExpression(expectStatement.parent) && - isIdentifier(expectStatement.parent.property) + ASTUtils.isIdentifier(expectStatement.parent.property) ) { isNegatedMatcher = true; matcher = expectStatement.parent.property.name; diff --git a/lib/rules/prefer-find-by.ts b/lib/rules/prefer-find-by.ts index fcc609a7..1150b848 100644 --- a/lib/rules/prefer-find-by.ts +++ b/lib/rules/prefer-find-by.ts @@ -1,4 +1,8 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { ReportFixFunction, RuleFix, @@ -7,7 +11,6 @@ import { import { isArrowFunctionExpression, isCallExpression, - isIdentifier, isMemberExpression, isObjectPattern, isProperty, @@ -41,7 +44,7 @@ function findRenderDefinitionDeclaration( if (variable) { return variable.defs .map(({ name }) => name) - .filter(isIdentifier) + .filter(ASTUtils.isIdentifier) .find(({ name }) => name === query); } @@ -104,7 +107,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ return { 'AwaitExpression > CallExpression'(node: TSESTree.CallExpression) { if ( - !isIdentifier(node.callee) || + !ASTUtils.isIdentifier(node.callee) || !WAIT_METHODS.includes(node.callee.name) ) { return; @@ -121,8 +124,8 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ // ensure here it's one of the sync methods that we are calling if ( isMemberExpression(argument.body.callee) && - isIdentifier(argument.body.callee.property) && - isIdentifier(argument.body.callee.object) && + ASTUtils.isIdentifier(argument.body.callee.property) && + ASTUtils.isIdentifier(argument.body.callee.object) && SYNC_QUERIES_COMBINATIONS.includes(argument.body.callee.property.name) ) { // shape of () => screen.getByText @@ -145,7 +148,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ return; } if ( - isIdentifier(argument.body.callee) && + ASTUtils.isIdentifier(argument.body.callee) && SYNC_QUERIES_COMBINATIONS.includes(argument.body.callee.name) ) { // shape of () => getByText @@ -183,7 +186,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ allVariableDeclarations.properties.some( (p) => isProperty(p) && - isIdentifier(p.key) && + ASTUtils.isIdentifier(p.key) && p.key.name === findByMethod ) ) { diff --git a/lib/rules/prefer-screen-queries.ts b/lib/rules/prefer-screen-queries.ts index fbf717d3..32f0f486 100644 --- a/lib/rules/prefer-screen-queries.ts +++ b/lib/rules/prefer-screen-queries.ts @@ -1,11 +1,14 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, ALL_QUERIES_COMBINATIONS } from '../utils'; import { isMemberExpression, isObjectPattern, isCallExpression, isProperty, - isIdentifier, isObjectExpression, } from '../node-utils'; @@ -26,7 +29,7 @@ function usesContainerOrBaseElement(node: TSESTree.CallExpression) { secondArgument.properties.some( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING.includes(property.key.name) ) ); @@ -68,7 +71,10 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ return { VariableDeclarator(node) { - if (!isCallExpression(node.init) || !isIdentifier(node.init.callee)) { + if ( + !isCallExpression(node.init) || + !ASTUtils.isIdentifier(node.init.callee) + ) { return; } const isWithinFunction = node.init.callee.name === 'within'; @@ -87,7 +93,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ .filter( (property) => isProperty(property) && - isIdentifier(property.key) && + ASTUtils.isIdentifier(property.key) && queriesRegex.test(property.key.name) ) .map( @@ -99,7 +105,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ return; } - if (isIdentifier(node.id)) { + if (ASTUtils.isIdentifier(node.id)) { withinDeclaredVariables.push(node.id.name); } }, @@ -122,10 +128,10 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ } if ( - isIdentifier(node) && + ASTUtils.isIdentifier(node) && isMemberExpression(node.parent) && isCallExpression(node.parent.object) && - isIdentifier(node.parent.object.callee) && + ASTUtils.isIdentifier(node.parent.object.callee) && node.parent.object.callee.name !== 'within' && node.parent.object.callee.name === 'render' && !usesContainerOrBaseElement(node.parent.object) @@ -136,7 +142,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ if ( isMemberExpression(node.parent) && - isIdentifier(node.parent.object) && + ASTUtils.isIdentifier(node.parent.object) && !isIdentifierAllowed(node.parent.object.name) ) { reportInvalidUsage(node); diff --git a/lib/rules/prefer-user-event.ts b/lib/rules/prefer-user-event.ts index aae27e65..0e5fc4f4 100644 --- a/lib/rules/prefer-user-event.ts +++ b/lib/rules/prefer-user-event.ts @@ -1,6 +1,6 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { TSESTree, ASTUtils } from '@typescript-eslint/experimental-utils'; import { createTestingLibraryRule } from '../create-testing-library-rule'; -import { isIdentifier, isMemberExpression } from '../node-utils'; +import { isMemberExpression } from '../node-utils'; export const RULE_NAME = 'prefer-user-event'; @@ -97,19 +97,19 @@ export default createTestingLibraryRule({ // testing library was imported, but fireEvent was not imported return; } - const fireEventAliasOrWildcard = isIdentifier(util) + const fireEventAliasOrWildcard = ASTUtils.isIdentifier(util) ? util.name : util.local.name; const fireEventUsed = - isIdentifier(node.object) && + ASTUtils.isIdentifier(node.object) && node.object.name === fireEventAliasOrWildcard; const fireEventFromWildcardUsed = isMemberExpression(node.object) && - isIdentifier(node.object.object) && + ASTUtils.isIdentifier(node.object.object) && node.object.object.name === fireEventAliasOrWildcard && - isIdentifier(node.object.property) && + ASTUtils.isIdentifier(node.object.property) && node.object.property.name === 'fireEvent'; if (!fireEventUsed && !fireEventFromWildcardUsed) { @@ -118,7 +118,7 @@ export default createTestingLibraryRule({ } if ( - !isIdentifier(node.property) || + !ASTUtils.isIdentifier(node.property) || !fireEventMappedMethods.includes(node.property.name) || allowedMethods.includes(node.property.name) ) { diff --git a/lib/rules/prefer-wait-for.ts b/lib/rules/prefer-wait-for.ts index 00d1fd5a..8b975a27 100644 --- a/lib/rules/prefer-wait-for.ts +++ b/lib/rules/prefer-wait-for.ts @@ -1,9 +1,12 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl } from '../utils'; import { isImportSpecifier, isMemberExpression, - isIdentifier, findClosestCallExpressionNode, } from '../node-utils'; @@ -97,7 +100,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ // member expression to get `foo.waitFor(() => {})` if ( isMemberExpression(node.parent) && - isIdentifier(node.parent.object) + ASTUtils.isIdentifier(node.parent.object) ) { methodReplacement = `${node.parent.object.name}.${methodReplacement}`; } @@ -143,7 +146,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ variable.references.forEach((reference) => { if ( isMemberExpression(reference.identifier.parent) && - isIdentifier(reference.identifier.parent.property) && + ASTUtils.isIdentifier(reference.identifier.parent.property) && DEPRECATED_METHODS.includes( reference.identifier.parent.property.name ) diff --git a/lib/rules/render-result-naming-convention.ts b/lib/rules/render-result-naming-convention.ts index 5bfa9715..f6686b6f 100644 --- a/lib/rules/render-result-naming-convention.ts +++ b/lib/rules/render-result-naming-convention.ts @@ -1,8 +1,11 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/experimental-utils'; +import { + ESLintUtils, + TSESTree, + ASTUtils, +} from '@typescript-eslint/experimental-utils'; import { getDocsUrl, hasTestingLibraryImportModule } from '../utils'; import { isCallExpression, - isIdentifier, isImportSpecifier, isMemberExpression, isObjectPattern, @@ -102,14 +105,14 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ const renderFunctionName = isCallExpression(node.init) && - isIdentifier(node.init.callee) && + ASTUtils.isIdentifier(node.init.callee) && node.init.callee.name; const renderFunctionObjectName = isCallExpression(node.init) && isMemberExpression(node.init.callee) && - isIdentifier(node.init.callee.property) && - isIdentifier(node.init.callee.object) && + ASTUtils.isIdentifier(node.init.callee.property) && + ASTUtils.isIdentifier(node.init.callee.object) && node.init.callee.property.name === 'render' && node.init.callee.object.name; @@ -124,7 +127,7 @@ export default ESLintUtils.RuleCreator(getDocsUrl)({ return; } - const renderResultName = isIdentifier(node.id) && node.id.name; + const renderResultName = ASTUtils.isIdentifier(node.id) && node.id.name; const isAllowedRenderResultName = ALLOWED_VAR_NAMES.includes( renderResultName ); From da46df679271b018cc89584c7163dca74e4da49a Mon Sep 17 00:00:00 2001 From: thomlom Date: Tue, 17 Nov 2020 09:36:34 +0100 Subject: [PATCH 2/3] refactor(ast-utils): migrate isAwaitExpression --- lib/node-utils.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/node-utils.ts b/lib/node-utils.ts index c2d3ff04..4b55da6c 100644 --- a/lib/node-utils.ts +++ b/lib/node-utils.ts @@ -125,13 +125,6 @@ export function hasThenProperty(node: TSESTree.Node): boolean { ); } -// TODO: remove this one and use ASTUtils one instead -export function isAwaitExpression( - node: TSESTree.Node -): node is TSESTree.AwaitExpression { - return node && node.type === AST_NODE_TYPES.AwaitExpression; -} - export function isArrowFunctionExpression( node: TSESTree.Node ): node is TSESTree.ArrowFunctionExpression { @@ -158,7 +151,7 @@ export function isImportDeclaration( export function isAwaited(node: TSESTree.Node): boolean { return ( - isAwaitExpression(node) || + ASTUtils.isAwaitExpression(node) || isArrowFunctionExpression(node) || isReturnStatement(node) ); @@ -209,7 +202,7 @@ export function isRenderVariableDeclarator( renderFunctions: string[] ): boolean { if (node.init) { - if (isAwaitExpression(node.init)) { + if (ASTUtils.isAwaitExpression(node.init)) { return ( node.init.argument && isRenderFunction( From 9d016d40454ac8b9dbccfa3d695edd14a585704f Mon Sep 17 00:00:00 2001 From: thomlom Date: Tue, 17 Nov 2020 09:42:23 +0100 Subject: [PATCH 3/3] refactor(ast-utils): use optional chaining for consistency --- lib/node-utils.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/node-utils.ts b/lib/node-utils.ts index 4b55da6c..26825717 100644 --- a/lib/node-utils.ts +++ b/lib/node-utils.ts @@ -15,13 +15,13 @@ export function isCallExpression( export function isNewExpression( node: TSESTree.Node ): node is TSESTree.NewExpression { - return node && node.type === 'NewExpression'; + return node?.type === 'NewExpression'; } export function isMemberExpression( node: TSESTree.Node ): node is TSESTree.MemberExpression { - return node && node.type === AST_NODE_TYPES.MemberExpression; + return node?.type === AST_NODE_TYPES.MemberExpression; } export function isLiteral( @@ -33,7 +33,7 @@ export function isLiteral( export function isImportSpecifier( node: TSESTree.Node ): node is TSESTree.ImportSpecifier { - return node && node.type === AST_NODE_TYPES.ImportSpecifier; + return node?.type === AST_NODE_TYPES.ImportSpecifier; } export function isImportNamespaceSpecifier( @@ -45,25 +45,25 @@ export function isImportNamespaceSpecifier( export function isImportDefaultSpecifier( node: TSESTree.Node ): node is TSESTree.ImportDefaultSpecifier { - return node && node.type === AST_NODE_TYPES.ImportDefaultSpecifier; + return node?.type === AST_NODE_TYPES.ImportDefaultSpecifier; } export function isBlockStatement( node: TSESTree.Node ): node is TSESTree.BlockStatement { - return node && node.type === AST_NODE_TYPES.BlockStatement; + return node?.type === AST_NODE_TYPES.BlockStatement; } export function isVariableDeclarator( node: TSESTree.Node ): node is TSESTree.VariableDeclarator { - return node && node.type === AST_NODE_TYPES.VariableDeclarator; + return node?.type === AST_NODE_TYPES.VariableDeclarator; } export function isObjectPattern( node: TSESTree.Node ): node is TSESTree.ObjectPattern { - return node && node.type === AST_NODE_TYPES.ObjectPattern; + return node?.type === AST_NODE_TYPES.ObjectPattern; } export function isProperty( @@ -75,7 +75,7 @@ export function isProperty( export function isJSXAttribute( node: TSESTree.Node ): node is TSESTree.JSXAttribute { - return node && node.type === AST_NODE_TYPES.JSXAttribute; + return node?.type === AST_NODE_TYPES.JSXAttribute; } export function findClosestCallExpressionNode( @@ -128,13 +128,13 @@ export function hasThenProperty(node: TSESTree.Node): boolean { export function isArrowFunctionExpression( node: TSESTree.Node ): node is TSESTree.ArrowFunctionExpression { - return node && node.type === AST_NODE_TYPES.ArrowFunctionExpression; + return node?.type === AST_NODE_TYPES.ArrowFunctionExpression; } export function isReturnStatement( node: TSESTree.Node ): node is TSESTree.ReturnStatement { - return node && node.type === AST_NODE_TYPES.ReturnStatement; + return node?.type === AST_NODE_TYPES.ReturnStatement; } export function isArrayExpression(