【问题标题】:Is there a way to know if Identifier node is a variable name when traversing AST?遍历AST时有没有办法知道Identifier节点是否是变量名?
【发布时间】:2022-10-18 19:17:03
【问题描述】:

我正在编写一个 babel 插件,我想收集特定表达式中使用的所有变量。为此,我将path.traverse()Identifier 访客一起使用。但是,这种方法并不理想,因为像属性名称之类的东西也被归类为标识符,而我只对实际变量感兴趣(在范围内声明/访问绑定的标识符 + 全局变量)。所以,目前,我正在做这样的事情:

expressionPath.traverse({
  Identifier(path) {
    const {node, parent} = path;
    if (!isVariableName({node, parent})) {
      return;
    }
    console.log('identifier is a variable name', node.name);
  }
});

function isVariableName({node, parent}) {
  if (types.isProperty(parent) || types.isMethod(parent)) {
    const isPropertyName = !parent.computed && node === parent.key;
    return !isPropertyName;
  }
  if (
    types.isMemberExpression(parent) ||
    types.isOptionalMemberExpression(parent)
  ) {
    const isPropertyName = !parent.computed && node === parent.property;
    return !isPropertyName;
  }
  if (types.isPrivateName(parent)) {
    return false;
  }
  return true;
}

我发现这也不理想,因为我需要考虑标识符的所有可能用例(我可能会错过一些,或者可能会有更多新的 JS 功能 - 例如私有类属性名称也是标识符)。 scope.getBinding() 在这里也没有多大帮助,因为全局变量没有绑定(就像属性名没有),实际上可以在范围内对某个标识符名称进行绑定,但标识符本身可以是属性名称.

你知道更好的解决方案吗?我还想知道是否正在声明或访问/变异变量,但我认为这是一个不同的问题。

谢谢!

【问题讨论】:

    标签: javascript babeljs babel-plugin


    【解决方案1】:

    原来 babel 已经提供了检查某个 Identifier 是否是变量的方法:

    1. path.isBingingIdentifier() 返回 true 如果标识符在范围内创建绑定(例如,正在声明一个变量)
    2. path.isReferencedIdentifier() - 如果正在引用变量(包括全局变量)。

    【讨论】:

      猜你喜欢
      • 2016-01-16
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多