Skip to content

Commit ea4d8c8

Browse files
committed
refactor: simplify various AST traversal methods usage
1 parent 264d7e1 commit ea4d8c8

File tree

7 files changed

+43
-58
lines changed

7 files changed

+43
-58
lines changed

packages/core/src/component/component-render-method.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ export function isFunctionOfRenderMethod(node: AST.TSESTreeFunction) {
4242
* @returns `true` if node is inside class component's render block, `false` if not
4343
*/
4444
export function isInsideRenderMethod(node: TSESTree.Node) {
45-
const predicate = (node: TSESTree.Node): node is TSESTree.MethodDefinition => {
45+
return O.isSome(AST.traverseUp(node, (node: TSESTree.Node) => {
4646
return isRenderMethodLike(node) && isClassComponent(node.parent.parent);
47-
};
48-
49-
return O.isSome(AST.traverseUp(node, predicate));
47+
}));
5048
}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import * as AST from "@eslint-react/ast";
22
import { O } from "@eslint-react/eff";
33
import type { TSESTree } from "@typescript-eslint/types";
4-
import { AST_NODE_TYPES } from "@typescript-eslint/types";
54

6-
import { isReactHook, isReactHookCall } from "./is";
5+
import { isReactHook } from "./is";
76

87
export function isInsideReactHook(node: TSESTree.Node) {
98
return O.exists(AST.traverseUpGuard(node, AST.isFunction), isReactHook);
109
}
11-
12-
export function isInsideReactHookCall(node: TSESTree.Node): boolean {
13-
return O.isSome(AST.traverseUp(node, n => AST.is(AST_NODE_TYPES.CallExpression)(n) && isReactHookCall(n)));
14-
}

packages/core/src/hook/is.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ export function isReactHook(node: AST.TSESTreeFunction) {
2121
* @param node The node to check.
2222
* @returns `true` if the node is a React Hook call, `false` otherwise.
2323
*/
24-
export function isReactHookCall(node: TSESTree.CallExpression) {
24+
export function isReactHookCall(node: TSESTree.Node) {
25+
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
2526
if (node.callee.type === AST_NODE_TYPES.Identifier) return isReactHookName(node.callee.name);
2627
if (node.callee.type === AST_NODE_TYPES.MemberExpression) {
2728
return node.callee.property.type === AST_NODE_TYPES.Identifier && isReactHookName(node.callee.property.name);

packages/plugins/eslint-plugin-react-x/src/rules/no-nested-components.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
useComponentCollector,
1010
useComponentCollectorLegacy,
1111
} from "@eslint-react/core";
12-
import { O } from "@eslint-react/eff";
12+
import { O, or } from "@eslint-react/eff";
1313
import * as JSX from "@eslint-react/jsx";
1414
import type { RuleFeature } from "@eslint-react/types";
1515
import type { TSESTree } from "@typescript-eslint/types";
@@ -123,7 +123,7 @@ export default createRule<[], MessageID>({
123123
}
124124
}
125125
for (const { name, node: component } of classComponents) {
126-
if (O.isNone(AST.traverseUp(component, node => isClassComponent(node) || isFunctionComponent(node)))) {
126+
if (O.isNone(AST.traverseUp(component, or(isClassComponent, isFunctionComponent)))) {
127127
continue;
128128
}
129129
context.report({

packages/plugins/eslint-plugin-react-x/src/rules/no-set-state-in-component-did-mount.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,19 @@ export default createRule<[], MessageID>({
4141
if (!context.sourceCode.text.includes("componentDidMount")) return {};
4242
function getReportDescriptor(node: TSESTree.CallExpression): O.Option<ReportDescriptor<MessageID>> {
4343
if (!isThisSetState(node)) return O.none();
44-
const maybeParentClass = AST.traverseUp(
45-
node,
46-
AST.isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression]),
44+
return F.pipe(
45+
O.Do,
46+
O.bind("clazz", () => AST.traverseUpGuard(node, isClassComponent)),
47+
O.bind("method", ({ clazz }) => AST.traverseUpStop(node, clazz, isComponentDidMount)),
48+
O.bind("upperScope", () => O.fromNullable(context.sourceCode.getScope(node).upper)),
49+
O.filter(({ clazz, method, upperScope }) =>
50+
method.parent === clazz.body && upperScope === context.sourceCode.getScope(method)
51+
),
52+
O.map(() => ({
53+
messageId: "noSetStateInComponentDidMount",
54+
node,
55+
})),
4756
);
48-
if (O.isNone(maybeParentClass)) return O.none();
49-
const parentClass = maybeParentClass.value;
50-
if (!isClassComponent(parentClass)) return O.none();
51-
const maybeParentMethod = AST.traverseUp(node, isComponentDidMount);
52-
if (O.isNone(maybeParentMethod)) return O.none();
53-
const parentMethod = maybeParentMethod.value;
54-
if (parentMethod.parent !== parentClass.body) return O.none();
55-
if (context.sourceCode.getScope(node).upper !== context.sourceCode.getScope(parentMethod)) return O.none();
56-
return O.some({
57-
messageId: "noSetStateInComponentDidMount",
58-
node,
59-
});
6057
}
6158
return {
6259
CallExpression: F.flow(getReportDescriptor, O.map(context.report)),

packages/plugins/eslint-plugin-react-x/src/rules/no-set-state-in-component-did-update.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,19 @@ export default createRule<[], MessageID>({
4141
if (!context.sourceCode.text.includes("componentDidUpdate")) return {};
4242
function getReportDescriptor(node: TSESTree.CallExpression): O.Option<ReportDescriptor<MessageID>> {
4343
if (!isThisSetState(node)) return O.none();
44-
const maybeParentClass = AST.traverseUp(
45-
node,
46-
AST.isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression]),
44+
return F.pipe(
45+
O.Do,
46+
O.bind("clazz", () => AST.traverseUpGuard(node, isClassComponent)),
47+
O.bind("method", ({ clazz }) => AST.traverseUpStop(node, clazz, isComponentDidUpdate)),
48+
O.bind("upperScope", () => O.fromNullable(context.sourceCode.getScope(node).upper)),
49+
O.filter(({ clazz, method, upperScope }) =>
50+
method.parent === clazz.body && upperScope === context.sourceCode.getScope(method)
51+
),
52+
O.map(() => ({
53+
messageId: "noSetStateInComponentDidUpdate",
54+
node,
55+
})),
4756
);
48-
if (O.isNone(maybeParentClass)) return O.none();
49-
const parentClass = maybeParentClass.value;
50-
if (!isClassComponent(parentClass)) return O.none();
51-
const maybeParentMethod = AST.traverseUp(node, isComponentDidUpdate);
52-
if (O.isNone(maybeParentMethod)) return O.none();
53-
const parentMethod = maybeParentMethod.value;
54-
if (parentMethod.parent !== parentClass.body) return O.none();
55-
if (context.sourceCode.getScope(node).upper !== context.sourceCode.getScope(parentMethod)) return O.none();
56-
return O.some({
57-
messageId: "noSetStateInComponentDidUpdate",
58-
node,
59-
});
6057
}
6158
return {
6259
CallExpression: F.flow(getReportDescriptor, O.map(context.report)),

packages/plugins/eslint-plugin-react-x/src/rules/no-set-state-in-component-will-update.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,19 @@ export default createRule<[], MessageID>({
4141
if (!context.sourceCode.text.includes("componentWillUpdate")) return {};
4242
function getReportDescriptor(node: TSESTree.CallExpression): O.Option<ReportDescriptor<MessageID>> {
4343
if (!isThisSetState(node)) return O.none();
44-
const maybeParentClass = AST.traverseUp(
45-
node,
46-
AST.isOneOf([AST_NODE_TYPES.ClassDeclaration, AST_NODE_TYPES.ClassExpression]),
44+
return F.pipe(
45+
O.Do,
46+
O.bind("clazz", () => AST.traverseUpGuard(node, isClassComponent)),
47+
O.bind("method", ({ clazz }) => AST.traverseUpStop(node, clazz, isComponentWillUpdate)),
48+
O.bind("upperScope", () => O.fromNullable(context.sourceCode.getScope(node).upper)),
49+
O.filter(({ clazz, method, upperScope }) =>
50+
method.parent === clazz.body && upperScope === context.sourceCode.getScope(method)
51+
),
52+
O.map(() => ({
53+
messageId: "noSetStateInComponentWillUpdate",
54+
node,
55+
})),
4756
);
48-
if (O.isNone(maybeParentClass)) return O.none();
49-
const parentClass = maybeParentClass.value;
50-
if (!isClassComponent(parentClass)) return O.none();
51-
const maybeParentMethod = AST.traverseUp(node, isComponentWillUpdate);
52-
if (O.isNone(maybeParentMethod)) return O.none();
53-
const parentMethod = maybeParentMethod.value;
54-
if (parentMethod.parent !== parentClass.body) return O.none();
55-
if (context.sourceCode.getScope(node).upper !== context.sourceCode.getScope(parentMethod)) return O.none();
56-
return O.some({
57-
messageId: "noSetStateInComponentWillUpdate",
58-
node,
59-
});
6057
}
6158
return {
6259
CallExpression: F.flow(getReportDescriptor, O.map(context.report)),

0 commit comments

Comments
 (0)