阻止使用 'some keyword' AST 解析器的 eslint 规则

eslint rules that prevent using 'some keyword' AST parser

我想使用 AST 解析器创建自定义 eslint 规则。

useEffect清理函数中,我想防止使用一些关键字。

import React, { useEffect } from 'react';


export const SomeReactFun = () => {
  useEffect(() => {
     return () => {
          // `Hello` is some keyword I want to prevent in using cleanup function.
          Hello.alert();
     }
  }, []);
}

这是我在 AST 解析器中自定义的解析函数。

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}` }
      });
    }
  };
}

但是这段代码不能这样防止

import React, { useEffect } from 'react';


export const SomeReactFun = () => {
  useEffect(() => {
     return () => {
          Hello.alert(); // works!
          Hello.someObject.a.alert(); // not works :)
     }
  }, []);
}

如何才能完全避免在 useEffect cleanup function 中使用 Hello 关键字?

TypeScript-ESLint 的网站上有一些关于编写 lint 规则的好文档,可以帮助您完成自定义 lint 规则

https://typescript-eslint.io/docs/development/custom-rules

您还可以使用我们的 playground 来查询 AST 并了解其结构,以便您可以编写适当的选择器

https://typescript-eslint.io/play#showAST=es