自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Eslint 的實(shí)現(xiàn)原理,其實(shí)挺簡(jiǎn)單

開發(fā) 開發(fā)工具
Eslint 是我們每天都在用的工具,我們會(huì)用它的 cli 或 api 來(lái)做代碼錯(cuò)誤檢查和格式檢查,有時(shí)候也會(huì)寫一些 rule 來(lái)做自定義的檢查和修復(fù)。

[[432341]]

Eslint 是我們每天都在用的工具,我們會(huì)用它的 cli 或 api 來(lái)做代碼錯(cuò)誤檢查和格式檢查,有時(shí)候也會(huì)寫一些 rule 來(lái)做自定義的檢查和修復(fù)。

雖然每天都用,但我們卻很少去了解它是怎么實(shí)現(xiàn)的。而了解 Eslint 的實(shí)現(xiàn)原理能幫助我們更好的使用它,更好的寫一些插件。

所以,這篇文章我們就通過(guò)源碼來(lái)探究下 Eslint 的實(shí)現(xiàn)原理吧。

Linter

Linter 是 eslint 最核心的類了,它提供了這幾個(gè) api:

  1. verify // 檢查 
  2. verifyAndFix // 檢查并修復(fù) 
  3.  
  4. getSourceCode // 獲取 AST 
  5. defineParser // 定義 Parser 
  6. defineRule // 定義 Rule 
  7. getRules // 獲取所有的 Rule 

SourceCode 就是指的 AST(抽象語(yǔ)法樹),Parser 是把源碼字符串解析成 AST 的,而 Rule 則是我們配置的那些對(duì) AST 進(jìn)行檢查的規(guī)則。這幾個(gè) api 比較容易理解。

Linter 主要的功能是在 verify 和 verifyAndFix 里實(shí)現(xiàn)的,當(dāng)命令行指定 --fix 或者配置文件指定 fix: true 就會(huì)調(diào)用 verifyAndFix 對(duì)代碼進(jìn)行檢查并修復(fù),否則會(huì)調(diào)用 verify 來(lái)進(jìn)行檢查。

那 verify 和 fix 是怎么實(shí)現(xiàn)的呢?這就是 eslint 最核心的部分了:

確定 parser

我們知道 Eslint 的 rule 是基于 AST 進(jìn)行檢查的,那就要先把源碼 parse 成 AST。而 eslint 的 parser 也是可以切換的,需要先找到用啥 parser:

默認(rèn)是 Eslint 自帶的 espree,也可以通過(guò)配置來(lái)切換成別的 parser,比如 @eslint/babel-parser、@typescript/eslint-parser 等。

下面是 resolve parser 的邏輯:

確定了 parser 之后,就是調(diào)用 parse 方法了。

parse 成 SourceCode

parser 的 parse 方法會(huì)把源碼解析為 AST,在 eslint 里是通過(guò) SourceCode 來(lái)封裝 AST 的。后面看到 SourceCode 就是指 AST.

有了 AST,就可以調(diào)用 rules 對(duì) AST 進(jìn)行檢查了

調(diào)用 rule 對(duì) SourceCode 進(jìn)行檢查,獲得 lintingProblems

parse 之后,會(huì)調(diào)用 runRules 方法對(duì) AST 進(jìn)行檢查,返回結(jié)果就是 problems,也就是有什么錯(cuò)誤和怎么修復(fù)的信息。

那 runRules 是怎么運(yùn)行的 rule 呢?

rule 的實(shí)現(xiàn)如下,就是注冊(cè)了對(duì)什么 AST 做什么檢查,這點(diǎn)和 babel 插件很類似。

runRules 會(huì)遍歷 AST,然后遇到不同的 AST 會(huì) emit 不同的事件。rule 里處理什么 AST 就會(huì)監(jiān)聽什么事件,這樣通過(guò)事件監(jiān)聽的方式,就可以在遍歷 AST 的過(guò)程中,執(zhí)行不同的 rule 了。

注冊(cè) listener:

遍歷 AST,emit 不同的事件,觸發(fā) listener:

這樣,遍歷完一遍 AST,也就調(diào)用了所有的 rules,這就是 rule 的運(yùn)行機(jī)制。

還有,遍歷的過(guò)程中會(huì)傳入 context,rule 里可以拿到,比如 scope、settings 等。

還有 ruleContext,調(diào)用 AST 的 listener 的時(shí)候可以拿到:

而 rule 里面就是通過(guò)這個(gè) report 的 api 進(jìn)行報(bào)錯(cuò)的,那這樣就可以把所有的錯(cuò)誤收集起來(lái),然后進(jìn)行打印。

這個(gè) problem 是什么呢?

linting problem

lint problem 是檢查的結(jié)果,也就是從哪一行(line)哪一列(column)到哪一行(endLine)哪一列(endColumn),有什么錯(cuò)誤(message)。

還有就是怎么修復(fù)(fix),修復(fù)其實(shí)就是 從那個(gè)下標(biāo)到哪個(gè)下標(biāo)(range),替換成什么文本(text)。

為什么 fix 是 range 返回和 text 這樣的結(jié)構(gòu)呢?因?yàn)樗膶?shí)現(xiàn)就是簡(jiǎn)單的字符串替換。

通過(guò)字符串替換實(shí)現(xiàn)自動(dòng) fix

遍歷完 AST,調(diào)用了所有的 rules,收集到了 linting problems 之后,就可以進(jìn)行 fix 了。

fix 部分的相關(guān)源碼是這樣的:

也就是 verify 進(jìn)行檢查,然后根據(jù) fix 信息自動(dòng) fix。

fix 其實(shí)就是個(gè)字符串替換:

有的同學(xué)可能注意到了,字符串替換為什么要加個(gè) while 循環(huán)呢?

因?yàn)槎鄠€(gè) fix 之間的 range 也就是替換的范圍可能是有重疊的,如果有重疊就放到下一次來(lái)修復(fù),這樣 while 循環(huán)最多修復(fù) 10 次,如果還有 fix 沒修復(fù)就不修了。

這就是 fix 的實(shí)現(xiàn)原理,通過(guò)字符串替換來(lái)實(shí)現(xiàn)的,如果有重疊就循環(huán)來(lái) fix。

preprocess 和 postprocess

其實(shí)核心的 verify 和 fix 的流程就是上面那些,但是 Eslint 還支持之前和之后做一些處理。也就是 pre 和 post 的 process,這些也是在插件里定義的。

  1. module.exports = { 
  2.     processors: { 
  3.         ".txt": { 
  4.             preprocess: function(text, filename) { 
  5.                 return [ // return an array of code blocks to lint 
  6.                     { text: code1, filename: "0.js" }, 
  7.                     { text: code2, filename: "1.js" }, 
  8.                 ]; 
  9.             }, 
  10.  
  11.             postprocess: function(messages, filename) { 
  12.                
  13.                 return [].concat(...messages); 
  14.             } 
  15.         } 
  16.     } 
  17. }; 

之前的處理是把非 js 文件解析出其中的一個(gè)個(gè) js 文件來(lái),這和 webpack 的 loader 很像,這使得 Eslint 可以處理非 JS 文件的 lint。

之后的處理呢?那肯定是處理 problems 啊,也就是 messages,可以過(guò)濾掉一些 messages,或者做一些修改之類的。

那 preprocess 和 postprocess 是怎么實(shí)現(xiàn)的呢?

這個(gè)就比較簡(jiǎn)單了,就是在 verify 之前和之后調(diào)用就行。

通過(guò) comment directives 來(lái)過(guò)濾掉一些 problems

我們知道 eslint 還支持通過(guò)注釋來(lái)配置,比如 /* eslint-disable */ /*eslint-enable*/ 這種。

那它是怎么實(shí)現(xiàn)的呢?

注釋的配置是通過(guò)掃描 AST 來(lái)收集所有的配置的,這種配置叫做 commentDirective,也就是哪行那列 Eslint 是否生效。

然后在 verify 結(jié)束的時(shí)候,對(duì)收集到的 linting problems 做一次過(guò)濾即可。

上面講的這些就是 Eslint 的實(shí)現(xiàn)原理:

Eslint 和 CLIEngine 類

Linter 是實(shí)現(xiàn)核心功能的,上面我們介紹過(guò)了,但是在命令行的場(chǎng)景下還需要處理一些命令行參數(shù),也就需要再包裝一層 CLIEngine,用來(lái)做文件的讀寫,命令行參數(shù)的解析。

它有 executeOnFiles 和 executeOnText 等 api,是基于 Linter 類的上層封裝。

但是 CLIEngine 并沒有直接暴露出去,而是又包裝了一層 EsLint 類,它只是一層比較好用的門面,隱藏了一些無(wú)關(guān)信息。

我們看下 eslint 最終暴露出來(lái)的這幾個(gè) api:

  • Linter 是核心的類,直接對(duì)文本進(jìn)行 lint
  • ESLint 是處理配置、讀寫文件等,然后調(diào)用 Linter 進(jìn)行 lint(中間的那層 CLIEngine 并沒有暴露出來(lái))
  • SourceCode 就是封裝 AST 用的
  • RuleTester 是用于 rule 測(cè)試的一些 api。

總結(jié)

我們通過(guò)源碼理清了 eslint 的實(shí)現(xiàn)原理:

ESLint 的核心類是 Linter,它分為這樣幾步:

  • preprocess,把非 js 文本處理成 js
  • 確定 parser(默認(rèn)是 espree)
  • 調(diào)用 parser,把源碼 parse 成 SourceCode(ast)
  • 調(diào)用 rules,對(duì) SourceCode 進(jìn)行檢查,返回 linting problems
  • 掃描出注釋中的 directives,對(duì) problems 進(jìn)行過(guò)濾
  • postprocess,對(duì) problems 做一次處理
  • 基于字符串替換實(shí)現(xiàn)自動(dòng) fix

除了核心的 Linter 類外,還有用于處理配置和讀寫文件的 CLIEngine 類,以及最終暴露出去的 Eslint 類。

這就是 Eslint 的實(shí)現(xiàn)原理,其實(shí)還是挺簡(jiǎn)單的:

基于 AST 做檢查,基于字符串做 fix,之前之后還有 pre 與 post 的process,支持注釋來(lái)配置過(guò)濾掉一些 problems。

把這些理清楚之后,就算是源碼層面掌握了 Eslint 了。

 

責(zé)任編輯:武曉燕 來(lái)源: 神光的編程秘籍
相關(guān)推薦

2011-03-18 10:26:47

Java對(duì)象

2023-10-30 13:31:22

Springboot工具Java

2017-11-22 10:53:22

2021-11-10 07:44:45

Svelte前端框架

2011-04-22 13:10:46

計(jì)算機(jī)邏輯門

2013-12-20 09:19:18

計(jì)算機(jī)學(xué)習(xí)

2022-07-12 09:55:34

Selenium爬取數(shù)據(jù)

2010-09-29 14:48:16

2016-12-26 18:05:00

單點(diǎn)登錄原理簡(jiǎn)單實(shí)現(xiàn)

2022-03-15 09:31:17

ESLint工作原理前端

2020-09-25 08:49:42

HashMap

2021-12-03 05:54:20

React組件前端

2021-06-23 06:20:52

微信正在輸入移動(dòng)應(yīng)用

2009-08-25 12:37:38

個(gè)人服務(wù)器架設(shè)

2022-05-06 09:22:25

Go泛型

2013-09-30 10:11:40

Windows 8技巧

2018-12-24 08:46:52

Kubernetes對(duì)象模型

2010-05-07 15:23:52

Oracle系統(tǒng)性能

2013-08-30 10:56:18

Windows 8.1

2022-03-16 22:24:50

ReactstateHooks
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)