Babel插件 - 在静态代码分析后将结构化信息作为输出

时间:2017-02-19 20:19:38

标签: javascript babeljs abstract-syntax-tree code-analysis static-analysis

我正在开发一个开发工具,可以为我提供一些代码指标。

我希望该工具能够浏览源文件,并根据导入值和每个计算用法(#loc)。

即。对于 lodash ,我想知道isEqualcloneDeep的用法。 我希望得到输出:

+------------+------------+---------+
|   Library  |  Imported  |   #LOC  |
+------------+------------+---------+
| Lodash     | isEqual    |       20|
| Lodash     | cloneDeep  |        4|
+------------+------------+---------+

工具

应该找到的示例文件
1 // aFile.js
2 import {isEqual, cloneDeep} from 'lodash'
3 // some code ..
4 if (isEqual(variableA, variableB)) {
5 //  ^^^^^^^
6 }
7 let myClonedObject = cloneDeep(myObject);
8 //                   ^^^^^^^^^

我开始实施一个babel插件,因为我知道它会让我轻松

  • 以可读格式(AST)解析代码
  • 访问所有importDeclaration
  • 获取相关参考资料
  • 计算用法

当前实施

export default function({ types: t }) {
  return {
    visitor: {
      ImportDeclaration(path, state) {
        if(path.get('source').node.value === 'lodash') {
          path.get('specifiers').forEach(function(specifier) {
            if(specifier.node.imported) {
              const importedIdentifierName = specifier.node.imported.name;
              if(importedIdentifierName === 'isEqual') {
                const isEqualLoc = new Set();
                const {referencePaths} = path.scope.getBinding(importedIdentifierName);
                referencePaths.forEach(function(referencePath) {
                  isEqualLOC.add(referencePath.node.loc.start.line);
                });
                console.log(isEqualLOC.size);
              }
            }
          });
        }
      }
    }
  };
};

对于此工具,我只对代码执行读取操作(无转换/生成)。

我的问题:如何将babel插件(lib / import /#loc)中生成的信息共享到babel-cli命令或任何其他API的结果?

我考虑过使用console.log记录结果(带有特定ID),但在我看来似乎是一种解决方法。 我想知道是否有一些关于从babel插件中暴露信息的明确API。

1 个答案:

答案 0 :(得分:1)

这看起来像是使用Babel的实用程序构建的更好的东西,但是在你自己的基础上实现。 Babel目前没有提供输出统计数据或任何东西的任何方法。例如,您可以将插件更改为

之类的脚本
const fs = require('fs');
const babylon = require('bablylon');
const traverse = require('babel-traverse');

const data = fs.readFileSync('./thing.js');
traverse(babylon.parse(data), {
  ImportDeclaration(path) {
    // ...
  },
});

// Do whatever output you want here