Skip to content

Commit 5c8ca8d

Browse files
authored
Handle chain expressions (hluisson#6)
1 parent 103309f commit 5c8ca8d

File tree

2 files changed

+69
-14
lines changed

2 files changed

+69
-14
lines changed

lib/rules/strict-logical-expressions.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,29 @@ export default createRule<Options, MessageIds>({
9797
}
9898
}
9999

100+
// Return the core identifier or expression
101+
function determineNode(originalNode: TSESTree.Expression) {
102+
let nodeToEvaluate = originalNode;
103+
if (nodeToEvaluate.type === TSESTree.AST_NODE_TYPES.ChainExpression) {
104+
nodeToEvaluate = nodeToEvaluate.expression;
105+
}
106+
107+
if (
108+
nodeToEvaluate.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
109+
nodeToEvaluate.property.type !==
110+
TSESTree.AST_NODE_TYPES.PrivateIdentifier
111+
) {
112+
nodeToEvaluate = nodeToEvaluate.property;
113+
}
114+
115+
return nodeToEvaluate;
116+
}
117+
100118
function checkLogicalExpression(
101119
expressionNode: TSESTree.LogicalExpression,
102120
checkRightNode: boolean
103121
) {
104-
let leftNode = expressionNode.left;
105-
if (
106-
leftNode.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
107-
leftNode.property.type !== TSESTree.AST_NODE_TYPES.PrivateIdentifier
108-
) {
109-
leftNode = leftNode.property;
110-
}
122+
const leftNode = determineNode(expressionNode.left);
111123

112124
if (leftNode.type === TSESTree.AST_NODE_TYPES.LogicalExpression) {
113125
checkLogicalExpression(leftNode, true);
@@ -116,13 +128,7 @@ export default createRule<Options, MessageIds>({
116128
}
117129

118130
if (checkRightNode) {
119-
let rightNode = expressionNode.right;
120-
if (
121-
rightNode.type === TSESTree.AST_NODE_TYPES.MemberExpression &&
122-
rightNode.property.type !== TSESTree.AST_NODE_TYPES.PrivateIdentifier
123-
) {
124-
rightNode = rightNode.property;
125-
}
131+
const rightNode = determineNode(expressionNode.right);
126132

127133
if (rightNode.type === TSESTree.AST_NODE_TYPES.Identifier) {
128134
checkAndReportIdentifier(rightNode, expressionNode.right);

tests/lib/rules/strict-logical-expressions.test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ ruleTester.run("strict-logical-expressions", rule, {
9797
options: [{ allowString: true }],
9898
filename: "react.tsx",
9999
},
100+
{
101+
code: [
102+
'type Bar = "bar"',
103+
"const obj: { foo: Bar } = { foo: 'bar' };",
104+
"<App>{obj?.foo && <Foo/>}</App>",
105+
].join("\n"),
106+
parserOptions: {
107+
ecmaFeatures: {
108+
jsx: true,
109+
},
110+
},
111+
filename: "react.tsx",
112+
},
100113
],
101114
invalid: [
102115
{
@@ -248,5 +261,41 @@ ruleTester.run("strict-logical-expressions", rule, {
248261
].join("\n"),
249262
filename: "react.tsx",
250263
},
264+
{
265+
code: [
266+
"const first = 100;",
267+
'const second = { foo: "bar" };',
268+
"<App>{first && second?.foo && <Foo/>}</App>",
269+
].join("\n"),
270+
errors: [{ messageId: "conditionErrorFalseyString" }],
271+
parserOptions: {
272+
ecmaFeatures: {
273+
jsx: true,
274+
},
275+
},
276+
output: [
277+
"const first = 100;",
278+
'const second = { foo: "bar" };',
279+
"<App>{first && !!second?.foo && <Foo/>}</App>",
280+
].join("\n"),
281+
filename: "react.tsx",
282+
},
283+
{
284+
code: [
285+
"const obj = { foo: 100 };",
286+
"<App>{obj?.foo && <Foo/>}</App>",
287+
].join("\n"),
288+
errors: [{ messageId: "conditionErrorFalseyNumber" }],
289+
parserOptions: {
290+
ecmaFeatures: {
291+
jsx: true,
292+
},
293+
},
294+
output: [
295+
"const obj = { foo: 100 };",
296+
"<App>{!!obj?.foo && <Foo/>}</App>",
297+
].join("\n"),
298+
filename: "react.tsx",
299+
},
251300
],
252301
});

0 commit comments

Comments
 (0)