All Tags
On this page

Eslint是如何工作的(深度源码解析)

#source-code #linter
avatar
jerrywu001
创建时间:2023-09-04 07:38:47

对于前端工程化,Eslint是一个非常重要的环节,它可以方便的检查出代码中不符合规范的地方,并给予错误提示,对前端规范来说非常重要!

阅读本文,您将收获

  • 如何直接调试eslint node_modules源码
  • 文件遍历以及文件配置生成过程
  • 如何将代码转换成ast
  • 如何利用ast和rules生成错误信息
  • 如何利用ast和rules进行代码修复

首先,我们需要了解几个重要的点:

  • ESLint/FlatESLint

    入口对应的类, 下图是它的调用方式

    路径:

    • node_modules\eslint\lib\eslint\eslint.js
    • node_modules\eslint\lib\eslint\flat-eslint.js

    Eslint class.png

  • CLIEngine 该类是 Eslint 的大脑,控制 Eslint 的执行流程,调用 api 时一般只需要操作 CLIEngine 即可

    路径: node_modules\eslint\lib\cli-engine\cli-engine.js

  • FileEnumerator遍历每个文件,并为文件绑定config

    路径: node_modules\eslint\lib\cli-engine\file-enumerator.js

  • Linter 该类是 Eslint 的执行总裁,配置文件加载、校验、修复都是该类来控制完成的

    路径: node_modules\eslint\lib\linter\linter.js

  • espree

    espree是基于Acorn实现的

    源码位置:node_modules\espree\dist\espree.cjs -> class Espree extends Parser

    Eslint使用它将代码转成ast,核心方法espree.parse,路径:node_modules\espree\dist\espree.cjs

    Linter类的初始化过程中会将espree缓存到internalSlotsMap全局对象中,后续verify环节会使用

    espree cache.png


如何调试?

  • 创建最小化eslint demo(字符串这里选择单引号规则)

    mkdir eslint-demo & cd eslint-demo
    
    npm init -y
    
    npm init @eslint/config
    # 选择js特性即可,字符串请选择单引号规则
    
    mkdir src & echo > src/index.js  'const a = "hello";'
    
  • 配置package.json,修改script

    {
     "name": "eslint-demo",
     "version": "1.0.0",
     "main": "index.js",
     "scripts": {
       "test": "npx eslint index.js"
     },
     "devDependencies": {
       "eslint": "^8.27.0"
     }
    }
    
  • 配置launch.json (后续打断点,按F5即可调试)

    mkdir .vscode & touch launch.json
    

    launch.json

    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Launch via NPM",
          "request": "launch",
          "runtimeArgs": [
            "run-script",
            "test"
          ],
          "runtimeExecutable": "npm",
          "skipFiles": [
            "<node_internals>/**"
          ],
          "type": "node"
        }
      ]
    }
    
  • 进入node_modules/eslint/bin/eslint.js

    找到以下代码所在行,打个断点,按F5即可开启调试

    require("../lib/cli").execute
    

文件遍历以及文件配置生成过程

从入口CLIEngine.executeOnFiles调用fileEnumerator.iterateFiles实现文件的遍历和配置生成,其中patterns为命令行传入的文件范围,它可以传一个固定的路径或者模式匹配,具体过程见下图:

02.file-config.png

save-config-array.png

如何将代码转换成tokens & ast

主要是调用spree.parse完成转换过程,具体过程见下图:

03.ast.png

如何利用ast和rules生成错误信息

通过调用runRules函数,并执行Traverser.traverse遍历ast tree, 并调用相应的检测函数进行校验,输出问题信息

值得注意的是,problems信息中包含fix数据,为后续fix代码做铺垫 image.png

04. problems.png

如何利用ast和rules进行代码修复

在上一步拿到problems信息的基础上,进一步分析,发现调用了applyFixes函数,即修复过程,具体过程见下图:

05.fix-image.png

好了,到此文章结束,感谢您的阅读,如果觉得对您有帮助,帮点个小红心,万分感谢~~