Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ export default createRule<Options, MessageIds>({
const lhs = lhsName.typeAnnotation?.typeAnnotation;

if (
!rhs ||
rhs.type !== AST_NODE_TYPES.NewExpression ||
rhs?.type !== AST_NODE_TYPES.NewExpression ||
rhs.callee.type !== AST_NODE_TYPES.Identifier
) {
return;
Expand Down
5 changes: 1 addition & 4 deletions packages/eslint-plugin/src/rules/no-dupe-class-members.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ export default createRule<Options, MessageIds>({
return;
}

if (
node.value &&
node.value.type === AST_NODE_TYPES.TSEmptyBodyFunctionExpression
) {
if (node.value?.type === AST_NODE_TYPES.TSEmptyBodyFunctionExpression) {
return;
}

Expand Down
5 changes: 1 addition & 4 deletions packages/eslint-plugin/src/rules/no-misused-promises.ts
Original file line number Diff line number Diff line change
Expand Up @@ -657,10 +657,7 @@ export default createRule<Options, MessageId>({
}

function checkJSXAttribute(node: TSESTree.JSXAttribute): void {
if (
node.value == null ||
node.value.type !== AST_NODE_TYPES.JSXExpressionContainer
) {
if (node.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) {
return;
}
const expressionContainer = services.esTreeNodeToTSNodeMap.get(
Expand Down
3 changes: 1 addition & 2 deletions packages/eslint-plugin/src/rules/no-redeclare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,9 +271,8 @@ export default createRule<Options, MessageIds>({
// Node.js or ES modules has a special scope.
if (
scope.type === ScopeType.global &&
scope.childScopes[0] &&
// The special scope's block is the Program node.
scope.block === scope.childScopes[0].block
scope.block === scope.childScopes[0]?.block
) {
findVariablesInScope(scope.childScopes[0]);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/eslint-plugin/src/rules/no-type-alias.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,7 @@ export default createRule<Options, MessageIds>({
if (
type.node.type === AST_NODE_TYPES.TSTypeOperator &&
['keyof', 'readonly'].includes(type.node.operator) &&
type.node.typeAnnotation &&
type.node.typeAnnotation.type === AST_NODE_TYPES.TSTupleType
type.node.typeAnnotation?.type === AST_NODE_TYPES.TSTupleType
) {
return true;
}
Expand Down
3 changes: 1 addition & 2 deletions packages/eslint-plugin/src/rules/prefer-namespace-keyword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ export default createRule({
const moduleType = context.sourceCode.getTokenBefore(node.id);

if (
moduleType &&
moduleType.type === AST_TOKEN_TYPES.Identifier &&
moduleType?.type === AST_TOKEN_TYPES.Identifier &&
moduleType.value === 'module'
) {
context.report({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,8 +568,7 @@ export default createRule<Options, MessageIds>({
}

if (
!assignmentExpression ||
assignmentExpression.type !== AST_NODE_TYPES.AssignmentExpression ||
assignmentExpression?.type !== AST_NODE_TYPES.AssignmentExpression ||
!isMemberAccessLike(assignmentExpression.left)
) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ import {
} from '../../util';
import { checkNullishAndReport } from './checkNullishAndReport';
import { compareNodes, NodeComparisonResult } from './compareNodes';
import { ComparisonType, NullishComparisonType } from './gatherLogicalOperands';
import {
ComparisonType,
NullishComparisonType,
Yoda,
} from './gatherLogicalOperands';

type LastChainOperandForReport = Omit<LastChainOperand, 'yoda'> & {
isYoda: boolean;
};

function includesType(
parserServices: ParserServicesWithTypeInformation,
Expand Down Expand Up @@ -257,6 +265,57 @@ const analyzeOrChainOperand: OperandAnalyzer = (
}
};

const resolveOperandSubset = (
previousOperand: ValidOperand,
lastChainOperand: LastChainOperand,
) => {
const isNameSubset =
compareNodes(
previousOperand.comparedName,
lastChainOperand.comparedName,
) === NodeComparisonResult.Subset;

if (lastChainOperand.yoda !== Yoda.Unknown) {
return {
comparedName: lastChainOperand.comparedName,
comparisonValue: lastChainOperand.comparisonValue,
isSubset: isNameSubset,
isYoda: lastChainOperand.yoda === Yoda.Yes,
};
}

const isValueSubset =
compareNodes(
previousOperand.comparedName,
lastChainOperand.comparisonValue,
) === NodeComparisonResult.Subset;

if (isNameSubset && !isValueSubset) {
return {
comparedName: lastChainOperand.comparedName,
comparisonValue: lastChainOperand.comparisonValue,
isSubset: true,
isYoda: false,
};
}

if (!isNameSubset && isValueSubset) {
return {
comparedName: lastChainOperand.comparisonValue,
comparisonValue: lastChainOperand.comparedName,
isSubset: true,
isYoda: true,
};
}

return {
comparedName: lastChainOperand.comparisonValue,
comparisonValue: lastChainOperand.comparisonValue,
isSubset: false,
isYoda: true,
};
};

/**
* Returns the range that needs to be reported from the chain.
* @param chain The chain of logical expressions.
Expand Down Expand Up @@ -306,7 +365,7 @@ function getReportDescriptor(
operator: '&&' | '||',
options: PreferOptionalChainOptions,
subChain: ValidOperand[],
lastChain: (LastChainOperand | ValidOperand) | undefined,
lastChain: (LastChainOperandForReport | ValidOperand) | undefined,
): ReportDescriptor<PreferOptionalChainMessageIds> {
const chain = lastChain ? [...subChain, lastChain] : subChain;
const lastOperand = chain[chain.length - 1];
Expand Down Expand Up @@ -606,7 +665,9 @@ export function analyzeChain(
// Things like x !== null && x !== undefined have two nodes, but they are
// one logical unit here, so we'll allow them to be grouped.
let subChain: (readonly ValidOperand[] | ValidOperand)[] = [];
let lastChain: LastChainOperand | ValidOperand | undefined = undefined;
let lastChain: LastChainOperandForReport | ValidOperand | undefined =
undefined;

const maybeReportThenReset = (
newChainSeed?: readonly [ValidOperand, ...ValidOperand[]],
): void => {
Expand Down Expand Up @@ -710,23 +771,27 @@ export function analyzeChain(
const lastOperand = subChain.flat().at(-1);

if (lastOperand && lastChainOperand) {
const comparisonResult = compareNodes(
lastOperand.comparedName,
lastChainOperand.comparedName,
);
const isValidLastChainOperand =
operator === '&&'
? isValidAndLastChainOperand
: isValidOrLastChainOperand;

const { comparedName, comparisonValue, isSubset, isYoda } =
resolveOperandSubset(lastOperand, lastChainOperand);
if (
comparisonResult === NodeComparisonResult.Subset &&
isSubset &&
isValidLastChainOperand(
lastChainOperand.comparisonValue,
comparisonValue,
lastChainOperand.comparisonType,
parserServices,
)
) {
lastChain = lastChainOperand;
lastChain = {
...lastChainOperand,
comparedName,
comparisonValue,
isYoda,
};
}
}
// check the leftovers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ import type { PreferOptionalChainOptions } from './PreferOptionalChainOptions';

import { isReferenceToGlobalFunction, isTypeFlagSet } from '../../util';

export const enum Yoda {
Yes,
No,
Unknown,
}
const enum ComparisonValueType {
Null = 'Null', // eslint-disable-line @typescript-eslint/internal/prefer-ast-types-enum
Undefined = 'Undefined',
Expand Down Expand Up @@ -66,7 +71,7 @@ export interface LastChainOperand {
comparedName: TSESTree.Node;
comparisonType: ComparisonType;
comparisonValue: TSESTree.Node;
isYoda: boolean;
yoda: Yoda;
node: TSESTree.BinaryExpression;
type: OperandValidity.Last;
}
Expand Down Expand Up @@ -257,7 +262,7 @@ export function gatherLogicalOperands(
// x !== something :(
const binaryComparisonChain = getBinaryComparisonChain(operand);
if (binaryComparisonChain) {
const { comparedName, comparedValue, isYoda } = binaryComparisonChain;
const { comparedName, comparedValue, yoda } = binaryComparisonChain;

switch (operand.operator) {
case '==':
Expand All @@ -270,9 +275,9 @@ export function gatherLogicalOperands(
comparedName,
comparisonType,
comparisonValue: comparedValue,
isYoda,
node: operand,
type: OperandValidity.Last,
yoda,
});
continue;
}
Expand All @@ -287,9 +292,9 @@ export function gatherLogicalOperands(
comparedName,
comparisonType,
comparisonValue: comparedValue,
isYoda,
node: operand,
type: OperandValidity.Last,
yoda,
});
continue;
}
Expand Down Expand Up @@ -430,29 +435,46 @@ export function gatherLogicalOperands(
return null;
}

function isMemberBasedExpression(
node: TSESTree.Expression | TSESTree.PrivateIdentifier,
): node is TSESTree.CallExpression | TSESTree.MemberExpression {
if (node.type === AST_NODE_TYPES.MemberExpression) {
return true;
}
if (
node.type === AST_NODE_TYPES.CallExpression &&
node.callee.type === AST_NODE_TYPES.MemberExpression
) {
return true;
}
return false;
}

function getBinaryComparisonChain(node: TSESTree.BinaryExpression) {
const { left, right } = node;
let isYoda = false;
const isLeftMemberExpression =
left.type === AST_NODE_TYPES.MemberExpression;
const isRightMemberExpression =
right.type === AST_NODE_TYPES.MemberExpression;
const isLeftMemberExpression = isMemberBasedExpression(left);
const isRightMemberExpression = isMemberBasedExpression(right);
if (isLeftMemberExpression && !isRightMemberExpression) {
const [comparedName, comparedValue] = [left, right];
return {
comparedName,
comparedValue,
isYoda,
yoda: Yoda.No,
};
}
if (!isLeftMemberExpression && isRightMemberExpression) {
const [comparedName, comparedValue] = [right, left];

isYoda = true;
return {
comparedName,
comparedValue,
isYoda,
yoda: Yoda.Yes,
};
}
if (isLeftMemberExpression && isRightMemberExpression) {
return {
comparedName: left,
comparedValue: right,
yoda: Yoda.Unknown,
};
}
return null;
Expand Down
13 changes: 3 additions & 10 deletions packages/eslint-plugin/src/rules/unified-signatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,7 @@ export default createRule<Options, MessageIds>({
}

function isThisParam(param: TSESTree.Parameter | undefined): boolean {
return (
param != null &&
param.type === AST_NODE_TYPES.Identifier &&
param.name === 'this'
);
return param?.type === AST_NODE_TYPES.Identifier && param.name === 'this';
}

function isThisVoidParam(param: TSESTree.Parameter | undefined) {
Expand Down Expand Up @@ -510,7 +506,7 @@ export default createRule<Options, MessageIds>({
a: TSESTree.TypeNode | undefined,
b: TSESTree.TypeNode | undefined,
): boolean {
return a === b || (a != null && b != null && a.type === b.type);
return a === b || (a != null && a.type === b?.type);
}

/* Returns the first index where `a` and `b` differ. */
Expand Down Expand Up @@ -595,10 +591,7 @@ export default createRule<Options, MessageIds>({
containingNode?: ContainingNode,
): void {
key ??= getOverloadKey(signature);
if (
currentScope &&
(containingNode ?? signature).parent === currentScope.parent
) {
if ((containingNode ?? signature).parent === currentScope?.parent) {
const overloads = currentScope.overloads.get(key);
if (overloads != null) {
overloads.push(signature);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ abstract class ThisScope extends Visitor {
// ```
case AST_NODE_TYPES.VariableDeclarator: {
const value = firstDef.node.init;
if (value == null || value.type !== AST_NODE_TYPES.ThisExpression) {
if (value?.type !== AST_NODE_TYPES.ThisExpression) {
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function isConstructorArgument(
function isPropertyOfObjectWithType(
property: TSESTree.Node | undefined,
): boolean {
if (!property || property.type !== AST_NODE_TYPES.Property) {
if (property?.type !== AST_NODE_TYPES.Property) {
return false;
}
const objectExpr = property.parent;
Expand Down
5 changes: 1 addition & 4 deletions packages/eslint-plugin/src/util/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,7 @@ export function arraysAreEqual<T>(
): boolean {
return (
a === b ||
(a != null &&
b != null &&
a.length === b.length &&
a.every((x, idx) => eq(x, b[idx])))
(a != null && a.length === b?.length && a.every((x, idx) => eq(x, b[idx])))
);
}

Expand Down
Loading