Skip to content

Commit 550c412

Browse files
authored
Use optional chaining (#1913)
1 parent 3a1e1bc commit 550c412

31 files changed

+61
-111
lines changed

rules/ast/is-empty-node.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function isEmptyNode(node, additionalEmpty) {
1010
return true;
1111
}
1212

13-
if (additionalEmpty && additionalEmpty(node)) {
13+
if (additionalEmpty?.(node)) {
1414
return true;
1515
}
1616

rules/ast/is-static-require.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
const {isStringLiteral} = require('./literal.js');
44

55
const isStaticRequire = node => Boolean(
6-
node
7-
&& node.type === 'CallExpression'
8-
&& node.callee
6+
node?.type === 'CallExpression'
97
&& node.callee.type === 'Identifier'
108
&& node.callee.name === 'require'
119
&& !node.optional

rules/consistent-function-scoping.js

+5-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function checkReferences(scope, parent, scopeManager) {
2121
const [definition] = resolved.defs;
2222

2323
// Skip recursive function name
24-
if (definition && definition.type === 'FunctionName' && resolved.name === definition.name.name) {
24+
if (definition?.type === 'FunctionName' && resolved.name === definition.name.name) {
2525
return false;
2626
}
2727

@@ -92,23 +92,20 @@ const reactHooks = [
9292
].flatMap(hookName => [hookName, `React.${hookName}`]);
9393

9494
const isReactHook = scope =>
95-
scope.block
96-
&& scope.block.parent
97-
&& scope.block.parent.callee
95+
scope.block?.parent?.callee
9896
&& isNodeMatches(scope.block.parent.callee, reactHooks);
9997

10098
const isArrowFunctionWithThis = scope =>
10199
scope.type === 'function'
102-
&& scope.block
103-
&& scope.block.type === 'ArrowFunctionExpression'
100+
&& scope.block?.type === 'ArrowFunctionExpression'
104101
&& (scope.thisFound || scope.childScopes.some(scope => isArrowFunctionWithThis(scope)));
105102

106103
const iifeFunctionTypes = new Set([
107104
'FunctionExpression',
108105
'ArrowFunctionExpression',
109106
]);
110-
const isIife = node => node
111-
&& iifeFunctionTypes.has(node.type)
107+
const isIife = node =>
108+
iifeFunctionTypes.has(node.type)
112109
&& node.parent.type === 'CallExpression'
113110
&& node.parent.callee === node;
114111

rules/custom-error-definition.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,15 @@ function * customErrorDefinition(context, node) {
137137
if (!nameExpression) {
138138
const nameProperty = body.find(node => isPropertyDefinition(node, 'name'));
139139

140-
if (!nameProperty || !nameProperty.value || nameProperty.value.value !== name) {
140+
if (!nameProperty?.value || nameProperty.value.value !== name) {
141141
yield {
142-
node: nameProperty && nameProperty.value ? nameProperty.value : constructorBodyNode,
142+
node: nameProperty?.value ? nameProperty.value : constructorBodyNode,
143143
message: `The \`name\` property should be set to \`${name}\`.`,
144144
};
145145
}
146146
} else if (nameExpression.expression.right.value !== name) {
147147
yield {
148-
node: nameExpression ? nameExpression.expression.right : constructorBodyNode,
148+
node: nameExpression?.expression.right ?? constructorBodyNode,
149149
message: `The \`name\` property should be set to \`${name}\`.`,
150150
};
151151
}

rules/filename-case.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ function splitFilename(filename) {
107107
for (const char of tailing) {
108108
const isIgnored = isIgnoredChar(char);
109109

110-
if (lastWord && lastWord.ignored === isIgnored) {
110+
if (lastWord?.ignored === isIgnored) {
111111
lastWord.word += char;
112112
} else {
113113
lastWord = {

rules/no-for-loop.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const defaultElementName = 'element';
1616
const isLiteralZero = node => isLiteral(node, 0);
1717
const isLiteralOne = node => isLiteral(node, 1);
1818

19-
const isIdentifierWithName = (node, name) => node && node.type === 'Identifier' && node.name === name;
19+
const isIdentifierWithName = (node, name) => node?.type === 'Identifier' && node.name === name;
2020

2121
const getIndexIdentifierName = forStatement => {
2222
const {init: variableDeclaration} = forStatement;
@@ -103,7 +103,7 @@ const getArrayIdentifier = (forStatement, indexIdentifierName) => {
103103
};
104104

105105
const isLiteralOnePlusIdentifierWithName = (node, identifierName) => {
106-
if (node && node.type === 'BinaryExpression' && node.operator === '+') {
106+
if (node?.type === 'BinaryExpression' && node.operator === '+') {
107107
return (isIdentifierWithName(node.left, identifierName) && isLiteralOne(node.right))
108108
|| (isIdentifierWithName(node.right, identifierName) && isLiteralOne(node.left));
109109
}
@@ -335,8 +335,8 @@ const create = context => {
335335

336336
return true;
337337
});
338-
const elementNode = elementReference && elementReference.identifier.parent.parent;
339-
const elementIdentifierName = elementNode && elementNode.id.name;
338+
const elementNode = elementReference?.identifier.parent.parent;
339+
const elementIdentifierName = elementNode?.id.name;
340340
const elementVariable = elementIdentifierName && resolveIdentifierName(elementIdentifierName, bodyScope);
341341

342342
const shouldFix = !someVariablesLeakOutOfTheLoop(node, [indexVariable, elementVariable].filter(Boolean), forScope);

rules/no-keyword-prefix.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function checkObjectPattern(report, node, options) {
6363
report(node, keyword);
6464
}
6565

66-
// Prevent checking righthand side of destructured object
66+
// Prevent checking right hand side of destructured object
6767
if (parent.key === node && parent.value !== node) {
6868
return true;
6969
}
@@ -113,7 +113,7 @@ const create = context => {
113113
parent.type === 'Property'
114114
|| parent.type === 'AssignmentPattern'
115115
) {
116-
if (parent.parent && parent.parent.type === 'ObjectPattern') {
116+
if (parent.parent.type === 'ObjectPattern') {
117117
const finished = checkObjectPattern(report, node, options);
118118
if (finished) {
119119
return;
@@ -145,11 +145,7 @@ const create = context => {
145145
].includes(parent.type)
146146
) {
147147
// Report only if the local imported identifier is invalid
148-
if (
149-
Boolean(keyword)
150-
&& parent.local
151-
&& parent.local.name === name
152-
) {
148+
if (Boolean(keyword) && parent.local?.name === name) {
153149
report(node, keyword);
154150
}
155151

rules/no-thenable.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,8 @@ const messages = {
1111
[MESSAGE_ID_CLASS]: 'Do not add `then` to a class.',
1212
};
1313

14-
const isStringThen = (node, context) => {
15-
const result = getStaticValue(node, context.getScope());
16-
17-
return result && result.value === 'then';
18-
};
14+
const isStringThen = (node, context) =>
15+
getStaticValue(node, context.getScope())?.value === 'then';
1916

2017
const cases = [
2118
// `{then() {}}`,

rules/no-unsafe-regex.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ const create = () => ({
3838
let flags;
3939
if (hasRegExp) {
4040
({pattern} = arguments_[0].regex);
41-
flags = arguments_[1] && arguments_[1].type === 'Literal'
41+
flags = arguments_[1]?.type === 'Literal'
4242
? arguments_[1].value
4343
: arguments_[0].regex.flags;
4444
} else {
4545
pattern = arguments_[0].value;
46-
flags = arguments_[1] && arguments_[1].type === 'Literal'
46+
flags = arguments_[1]?.type === 'Literal'
4747
? arguments_[1].value
4848
: '';
4949
}

rules/no-unused-properties.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@ const getDeclaratorOrPropertyValue = declaratorOrProperty =>
1111
|| declaratorOrProperty.value;
1212

1313
const isMemberExpressionCall = memberExpression =>
14-
memberExpression.parent
15-
&& memberExpression.parent.type === 'CallExpression'
14+
memberExpression.parent.type === 'CallExpression'
1615
&& memberExpression.parent.callee === memberExpression;
1716

1817
const isMemberExpressionAssignment = memberExpression =>
19-
memberExpression.parent
20-
&& memberExpression.parent.type === 'AssignmentExpression';
18+
memberExpression.parent.type === 'AssignmentExpression';
2119

2220
const isMemberExpressionComputedBeyondPrediction = memberExpression =>
2321
memberExpression.computed

rules/no-useless-promise-resolve-reject.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function fix(callExpression, isInTryStatement, sourceCode) {
101101
}
102102

103103
const {callee, parent, arguments: [errorOrValue]} = callExpression;
104-
if (errorOrValue && errorOrValue.type === 'SpreadElement') {
104+
if (errorOrValue?.type === 'SpreadElement') {
105105
return;
106106
}
107107

@@ -122,7 +122,7 @@ function fix(callExpression, isInTryStatement, sourceCode) {
122122

123123
let text = errorOrValue ? sourceCode.getText(errorOrValue) : '';
124124

125-
if (errorOrValue && errorOrValue.type === 'SequenceExpression') {
125+
if (errorOrValue?.type === 'SequenceExpression') {
126126
text = `(${text})`;
127127
}
128128

@@ -155,7 +155,7 @@ function fix(callExpression, isInTryStatement, sourceCode) {
155155
} else if (parent.type === 'ReturnStatement') {
156156
text = `return${text ? ' ' : ''}${text};`;
157157
} else {
158-
if (errorOrValue && errorOrValue.type === 'ObjectExpression') {
158+
if (errorOrValue?.type === 'ObjectExpression') {
159159
text = `(${text})`;
160160
}
161161

rules/no-useless-undefined.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ const shouldIgnore = node => {
6363
} else if (
6464
node.type === 'MemberExpression'
6565
&& node.computed === false
66-
&& node.property
6766
&& node.property.type === 'Identifier'
6867
) {
6968
name = node.property.name;
@@ -104,7 +103,7 @@ const create = context => {
104103
const listener = (fix, checkFunctionReturnType) => node => {
105104
if (checkFunctionReturnType) {
106105
const functionNode = getFunction(context.getScope());
107-
if (functionNode && functionNode.returnType) {
106+
if (functionNode?.returnType) {
108107
return;
109108
}
110109
}

rules/prefer-array-find.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -239,11 +239,10 @@ const fixDestructuringAndReplaceFilter = (sourceCode, node) => {
239239
};
240240

241241
const isAccessingZeroIndex = node =>
242-
node.parent
243-
&& node.parent.type === 'MemberExpression'
242+
node.parent.type === 'MemberExpression'
244243
&& node.parent.computed === true
245244
&& node.parent.object === node
246-
&& node.parent.property?.type === 'Literal'
245+
&& node.parent.property.type === 'Literal'
247246
&& node.parent.property.raw === '0';
248247

249248
const isDestructuringFirstElement = node => {
@@ -252,7 +251,6 @@ const isDestructuringFirstElement = node => {
252251
&& right
253252
&& right === node
254253
&& left.type === 'ArrayPattern'
255-
&& left.elements
256254
&& left.elements.length === 1
257255
&& left.elements[0].type !== 'RestElement';
258256
};

rules/prefer-json-parse-buffer.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ function getIdentifierDeclaration(node, scope) {
5959
return getIdentifierDeclaration(identifier.parent.init, variable.scope);
6060
}
6161

62-
const isUtf8EncodingStringNode = (node, scope) => {
63-
const staticValue = getStaticValue(node, scope);
64-
return staticValue && isUtf8EncodingString(staticValue.value);
65-
};
62+
const isUtf8EncodingStringNode = (node, scope) =>
63+
isUtf8EncodingString(getStaticValue(node, scope)?.value);
6664

6765
const isUtf8EncodingString = value => {
6866
if (typeof value !== 'string') {

rules/prefer-keyboard-event-key.js

+8-17
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,20 @@ const keys = new Set([
1515
]);
1616

1717
const isPropertyNamedAddEventListener = node =>
18-
node
19-
&& node.type === 'CallExpression'
20-
&& node.callee
18+
node?.type === 'CallExpression'
2119
&& node.callee.type === 'MemberExpression'
22-
&& node.callee.property
2320
&& node.callee.property.name === 'addEventListener';
2421

2522
const getEventNodeAndReferences = (context, node) => {
2623
const eventListener = getMatchingAncestorOfType(node, 'CallExpression', isPropertyNamedAddEventListener);
27-
const callback = eventListener && eventListener.arguments && eventListener.arguments[1];
28-
switch (callback && callback.type) {
24+
const callback = eventListener?.arguments[1];
25+
switch (callback?.type) {
2926
case 'ArrowFunctionExpression':
3027
case 'FunctionExpression': {
3128
const eventVariable = context.getDeclaredVariables(callback)[0];
32-
const references = eventVariable && eventVariable.references;
29+
const references = eventVariable?.references;
3330
return {
34-
event: callback.params && callback.params[0],
31+
event: callback.params[0],
3532
references,
3633
};
3734
}
@@ -43,10 +40,7 @@ const getEventNodeAndReferences = (context, node) => {
4340
};
4441

4542
const isPropertyOf = (node, eventNode) =>
46-
node
47-
&& node.parent
48-
&& node.parent.type === 'MemberExpression'
49-
&& node.parent.object
43+
node?.parent?.type === 'MemberExpression'
5044
&& node.parent.object === eventNode;
5145

5246
// The third argument is a condition function, as one passed to `Array#filter()`
@@ -133,7 +127,7 @@ const create = context => ({
133127

134128
Property(node) {
135129
// Destructured case
136-
const propertyName = node.value && node.value.name;
130+
const propertyName = node.value.name;
137131
if (!keys.has(propertyName)) {
138132
return;
139133
}
@@ -147,10 +141,7 @@ const create = context => ({
147141
node,
148142
'VariableDeclarator',
149143
);
150-
const initObject
151-
= nearestVariableDeclarator
152-
&& nearestVariableDeclarator.init
153-
&& nearestVariableDeclarator.init;
144+
const initObject = nearestVariableDeclarator?.init;
154145

155146
// Make sure initObject is a reference of eventVariable
156147
if (

rules/prefer-native-coercion-functions.js

+3-6
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@ const nativeCoercionFunctionNames = new Set(['String', 'Number', 'BigInt', 'Bool
1111
const arrayMethodsWithBooleanCallback = new Set(['every', 'filter', 'find', 'findLast', 'findIndex', 'findLastIndex', 'some']);
1212

1313
const isNativeCoercionFunctionCall = (node, firstArgumentName) =>
14-
node
15-
&& node.type === 'CallExpression'
14+
node?.type === 'CallExpression'
1615
&& !node.optional
1716
&& node.callee.type === 'Identifier'
1817
&& nativeCoercionFunctionNames.has(node.callee.name)
19-
&& node.arguments[0]
20-
&& node.arguments[0].type === 'Identifier'
18+
&& node.arguments[0]?.type === 'Identifier'
2119
&& node.arguments[0].name === firstArgumentName;
2220

2321
const isIdentityFunction = node =>
@@ -33,8 +31,7 @@ const isIdentityFunction = node =>
3331
node.body.type === 'BlockStatement'
3432
&& node.body.body.length === 1
3533
&& node.body.body[0].type === 'ReturnStatement'
36-
&& node.body.body[0].argument
37-
&& node.body.body[0].argument.type === 'Identifier'
34+
&& node.body.body[0].argument?.type === 'Identifier'
3835
&& node.body.body[0].argument.name === node.params[0].name
3936
);
4037

rules/prefer-negative-index.js

-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ const getMemberName = node => {
5454

5555
if (
5656
type === 'MemberExpression'
57-
&& property
5857
&& property.type === 'Identifier'
5958
) {
6059
return property.name;

rules/prefer-number-properties.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const globalObjects = {
2424

2525
const isNegative = node => {
2626
const {parent} = node;
27-
return parent && parent.type === 'UnaryExpression' && parent.operator === '-' && parent.argument === node;
27+
return parent.type === 'UnaryExpression' && parent.operator === '-' && parent.argument === node;
2828
};
2929

3030
function checkProperty({node, path: [name]}, sourceCode) {

rules/prefer-prototype-methods.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,8 @@ function create(context) {
5151
yield fixer.replaceText(node.object, `${constructorName}.prototype`);
5252

5353
if (
54-
node.object
55-
&& (
56-
node.object.type === 'ArrayExpression'
57-
|| node.object.type === 'ObjectExpression'
58-
)
54+
node.object.type === 'ArrayExpression'
55+
|| node.object.type === 'ObjectExpression'
5956
) {
6057
yield * fixSpaceAroundKeyword(fixer, node.parent.parent, context.getSourceCode());
6158
}

0 commit comments

Comments
 (0)