diff --git a/.eslintrc.json b/.eslintrc.json index e84c8d766..3b0c8237d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -17,7 +17,6 @@ "@rebeccastevens/eslint-config/modern", "@rebeccastevens/eslint-config/typescript", "@rebeccastevens/eslint-config/common-overrides", - "plugin:eslint-plugin/recommended", "plugin:prettier/recommended", "prettier" ], @@ -60,6 +59,12 @@ "functional/no-throw-statement": "off" } }, + // Source files. + { + "files": ["src/**/*"], + "extends": ["plugin:eslint-plugin/recommended"], + "rules": {} + }, // FIXME: This override is defined in the upsteam; it shouldn't need to be redefined here. Why? { "files": ["**/*.md/**"], diff --git a/package.json b/package.json index d984ba070..1d70b3e53 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@commitlint/cli": "^13.2.1", "@commitlint/config-conventional": "^13.2.0", "@istanbuljs/nyc-config-typescript": "^1.0.1", - "@rebeccastevens/eslint-config": "^1.1.4", + "@rebeccastevens/eslint-config": "^1.1.5", "@rollup/plugin-commonjs": "^21.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.0.5", diff --git a/src/common/ignore-options.ts b/src/common/ignore-options.ts index 5f0016faf..2df431513 100644 --- a/src/common/ignore-options.ts +++ b/src/common/ignore-options.ts @@ -8,6 +8,7 @@ import { hasID, hasKey, isAssignmentExpression, + isDefined, isPropertyDefinition, isExpressionStatement, isIdentifier, @@ -115,34 +116,34 @@ function getNodeIdentifierText( node: TSESTree.Node | null | undefined, context: RuleContext ): string | undefined { - return node === undefined || node === null - ? undefined - : isIdentifier(node) - ? node.name - : hasID(node) - ? getNodeIdentifierText(node.id, context) - : hasKey(node) - ? getNodeIdentifierText(node.key, context) - : isAssignmentExpression(node) - ? getNodeIdentifierText(node.left, context) - : isMemberExpression(node) - ? `${getNodeIdentifierText(node.object, context)}.${getNodeIdentifierText( - node.property, - context - )}` - : isThisExpression(node) - ? "this" - : isUnaryExpression(node) - ? getNodeIdentifierText(node.argument, context) - : isExpressionStatement(node) - ? context.getSourceCode().getText(node) - : isTSArrayType(node) || - isTSIndexSignature(node) || - isTSTupleType(node) || - isTSTypeAnnotation(node) || - isTSTypeLiteral(node) || - isTSTypeReference(node) - ? getNodeIdentifierText(node.parent, context) + return isDefined(node) + ? isIdentifier(node) + ? node.name + : hasID(node) && isDefined(node.id) + ? getNodeIdentifierText(node.id, context) + : hasKey(node) && isDefined(node.key) + ? getNodeIdentifierText(node.key, context) + : isAssignmentExpression(node) + ? getNodeIdentifierText(node.left, context) + : isMemberExpression(node) + ? `${getNodeIdentifierText(node.object, context)}.${getNodeIdentifierText( + node.property, + context + )}` + : isThisExpression(node) + ? "this" + : isUnaryExpression(node) + ? getNodeIdentifierText(node.argument, context) + : isExpressionStatement(node) + ? context.getSourceCode().getText(node) + : isTSArrayType(node) || + isTSIndexSignature(node) || + isTSTupleType(node) || + isTSTypeAnnotation(node) || + isTSTypeLiteral(node) || + isTSTypeReference(node) + ? getNodeIdentifierText(node.parent, context) + : undefined : undefined; } diff --git a/src/rules/prefer-tacit.ts b/src/rules/prefer-tacit.ts index 7e5acd5cb..acbed68c5 100644 --- a/src/rules/prefer-tacit.ts +++ b/src/rules/prefer-tacit.ts @@ -11,6 +11,7 @@ import { createRule, getESTreeNode, getTypeOfNode } from "~/util/rule"; import { isBlockStatement, isCallExpression, + isDefined, isFunctionLike, isIdentifier, isReturnStatement, @@ -101,8 +102,7 @@ function isCallerViolation( const declaration = getESTreeNode(tsDeclaration, context); return ( - (declaration !== null && - declaration !== undefined && + (isDefined(declaration) && (isFunctionLike(declaration) || isTSFunctionType(declaration)) && declaration.params.length === caller.arguments.length) || // Check for optional params. diff --git a/src/util/tree.ts b/src/util/tree.ts index e1460ed60..e5de771d6 100644 --- a/src/util/tree.ts +++ b/src/util/tree.ts @@ -4,6 +4,7 @@ import type { TSESTree } from "@typescript-eslint/experimental-utils"; import { isCallExpression, isClassLike, + isDefined, isFunctionExpressionLike, isFunctionLike, isIdentifier, @@ -27,9 +28,9 @@ function getAncestorOfType( ): T | null { return checker(node, child) ? node - : node.parent === null || node.parent === undefined - ? null - : getAncestorOfType(checker, node.parent, node); + : isDefined(node.parent) + ? getAncestorOfType(checker, node.parent, node) + : null; } /** @@ -57,11 +58,9 @@ export function inClass(node: TSESTree.Node): boolean { export function inReadonly(node: TSESTree.Node): boolean { // For nested cases, we shouldn't look for any parent, but the immediate parent. if ( - node.parent !== null && - node.parent !== undefined && + isDefined(node.parent) && isTSTypeLiteral(node.parent) && - node.parent.parent !== null && - node.parent.parent !== undefined && + isDefined(node.parent.parent) && isTSTypeAnnotation(node.parent.parent) ) { return false; @@ -102,8 +101,7 @@ export function isInReturnType(node: TSESTree.Node): boolean { return ( getAncestorOfType( (n): n is TSESTree.Node => - n.parent !== undefined && - n.parent !== null && + isDefined(n.parent) && isFunctionLike(n.parent) && n.parent.returnType === n, node diff --git a/src/util/typeguard.ts b/src/util/typeguard.ts index aac9a21c5..170d57168 100644 --- a/src/util/typeguard.ts +++ b/src/util/typeguard.ts @@ -334,6 +334,10 @@ export function hasKey( return Object.prototype.hasOwnProperty.call(node, "key"); } +export function isDefined(value: T | null | undefined): value is T { + return value !== null && value !== undefined; +} + /* * TS types type guards. */ diff --git a/yarn.lock b/yarn.lock index 80d296ba6..a4d579479 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1154,10 +1154,10 @@ dependencies: "@octokit/openapi-types" "^11.2.0" -"@rebeccastevens/eslint-config@^1.1.4": - version "1.1.4" - resolved "https://registry.yarnpkg.com/@rebeccastevens/eslint-config/-/eslint-config-1.1.4.tgz#97e656678d97fa3941f6aa817b1eda9a92ac6a98" - integrity sha512-nEWzZDhuSwYXVQ48Scovcrlw2WaXekEo1xSiZxBqRo3WyXLf2CsyJYi3wq3DoCIsPpBPmzZ8RostREw/vPDedw== +"@rebeccastevens/eslint-config@^1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@rebeccastevens/eslint-config/-/eslint-config-1.1.5.tgz#9b640323c99f0969f0aa59a3198f5609b3f82e94" + integrity sha512-Gd/g6CqCPOuycycsD3RFAaQ84wobusEA+60dyXvODj66nLaqvS78HcCrWbL69Y28XL5SuXJB8ukB/LK52AbE3A== dependencies: deepmerge-ts "^1.0.1"