Reputation: 417
I want to make a custom eslint
rule using the AST parser.
In the useEffect
cleanup function, I want to prevent using some keywords.
import React, { useEffect } from 'react';
export const SomeReactFun = () => {
useEffect(() => {
return () => {
// `Hello` is some keyword I want to prevent in using cleanup function.
Hello.alert();
}
}, []);
}
this is my custom parse function in AST parser.
export default function (context) {
const filename = context.getFilename();
if (filename.includes(".test.ts")) return {};
return {
Identifier: (node) => {
if (node.name !== "useEffect" || node.parent.type !== "CallExpression")
return {};
const arrayExpressionBody = node.parent.arguments[0];
if (arrayExpressionBody.type !== "ArrowFunctionExpression") return {};
const arrowFunctionBody = arrayExpressionBody.body;
if (arrowFunctionBody.type !== "BlockStatement") return {};
const returnStatement = arrowFunctionBody.body.find((functionNode) => {
if (functionNode.type === "ReturnStatement") return true;
return false;
});
if (!returnStatement || returnStatement.type !== "ReturnStatement")
return {};
const returnStateArgument = returnStatement.argument;
if (returnStateArgument.type !== "ArrowFunctionExpression") return {};
const blockStatementInReturnState = returnStateArgument.body;
if (blockStatementInReturnState.type !== "BlockStatement") return {};
const isHelloUsedInClenaup = blockStatementInReturnState.body.find(
(nodeBody) => {
if (nodeBody.type !== "ExpressionStatement") return false;
console.log(nodeBody.expression);
if (
nodeBody.expression.type === "CallExpression" &&
nodeBody.expression.callee.object.name === "Hello"
) {
return false;
}
if (
nodeBody.expression.type === "Identifier" &&
nodeBody.expression.name === "Hello"
)
return false;
}
);
if (!isHelloUsedInClenaup) return {};
context.report({
node: isHelloUsedInClenaup,
message: "ERROR, do not use `Hello` in cleanup function",
data: { explanation: `${node.loc}` }
});
}
};
}
But this code can't prevent like this
import React, { useEffect } from 'react';
export const SomeReactFun = () => {
useEffect(() => {
return () => {
Hello.alert(); // works!
Hello.someObject.a.alert(); // not works :)
}
}, []);
}
How can I prevent using the Hello
keyword in useEffect cleanup function
completely?
Upvotes: 2
Views: 502
Reputation: 3243
There's some good docs on writing lint rules on TypeScript-ESLint's website which can help walk you through custom lint rules
https://typescript-eslint.io/docs/development/custom-rules
You can also use our playground to interrogate the AST and learn its structure so that you can write appropriate selectors
https://typescript-eslint.io/play#showAST=es
Upvotes: 1