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

隱藏在 Eslint 的Fix 功能中的可以用來面試的算法題

開發(fā) 前端 算法
babel 和 eslint 都可以修改代碼,babel 是操作了 AST,打印代碼的時候就會生成不同的代碼,而 eslint 則是一部分 rule 支持自動 fix,當(dāng)開啟了 --fix 的時候就會自動修復(fù)。

[[422353]]

我們知道 eslint 支持 fix,當(dāng)添加了 --fix 參數(shù)部分 rule 可以自動修復(fù)問題。

有沒有想過,這種功能是怎么實現(xiàn)的?babel 也能轉(zhuǎn)換代碼,它和 eslint 生成代碼的原理一樣么?

babel

babel 分為 parse、transform、generate 3 步。

圖片

在 transform 階段轉(zhuǎn)換完 AST 代碼之后,在 generate 階段會遞歸打印 AST 成目標(biāo)代碼。

generate 的原理就是遞歸根據(jù)每個 AST 的信息拼接字符串:

所以我們在插件里面改動了 AST,最終的代碼也會改。

eslint

eslint 的 rule 可以對 AST 進(jìn)行檢查,然后通過 context.report 報錯,還可以指定如何修復(fù):

自定義 rule 格式如下:

  1. module.exports = { 
  2.      meta: { 
  3.          fixable: true 
  4.      }, 
  5.      create(context) { 
  6.          return { 
  7.             // 指定 AST 的類型 
  8.             ObjectExpression(node) { 
  9.                 // 一系列檢查 
  10.                 context.report({ 
  11.                     node, 
  12.                     message: 'xxx 有錯誤'
  13.                     loc: node.loc, 
  14.                     *fix(fixer) { 
  15.                         yield fixer.replaceTextRange([rangeStart,rangeEnd], '替換的文本'); 
  16.                     } 
  17.                 }); 
  18.              } 
  19.          }; 
  20.      } 
  21.  }; 

其中 fix 選項就是用于問題自動修復(fù)的,通過 fixer 的 api。

fixer 有這些 api 可用:

  1. insertTextAfter(nodeOrToken, text); 
  2. insertTextAfterRange(range, text); 
  3. insertTextBefore(nodeOrToken, text); 
  4. insertTextBeforeRange(range, text); 
  5.  
  6. remove(nodeOrToken); 
  7. removeRange(range); 
  8.  
  9. replaceText(nodeOrToken, text); 
  10. replaceTextRange(range, text); 

特別容易記,就是增、刪、改 3類,增分為在前面插入和在后面插入,每一類都支持基于 token 來修改 text 或者基于 range(下標(biāo)范圍)。

AST 中每個節(jié)點都保留了 range 的信息,也就是在源代碼的下標(biāo)是從哪到哪,這樣就可以根據(jù) range 來修改代碼,或者根據(jù) AST 查到 range 再去修改代碼。

那知道了對什么 range 做什么操作之后,是怎么自動修改代碼的呢?

下面是 eslint 中 fix 代碼的源碼:

  1. // 源碼 
  2. const originalText = sourceCode.text; 
  3. // 第一個 range 的開始 
  4. const start = fixes[0].range[0]; 
  5. // 最后一個 range 的結(jié)束 
  6. const end = fixes[fixes.length - 1].range[1]; 
  7. // 替換的文本 
  8. let text = ""
  9. let lastPos = Number.MIN_SAFE_INTEGER; 
  10.  
  11. for (const fix of fixes) { 
  12.     if (fix.range[0] >= 0) { 
  13.         // 截取 range 的左邊的字符串,從當(dāng)前 range 和 上一個 range 的右邊位置取大的 
  14.         text += originalText.slice(Math.max(0, start, lastPos), fix.range[0]); 
  15.     } 
  16.     // 拼接上修復(fù)的文本 
  17.     text += fix.text; 
  18.     // range 右邊的位置 
  19.     lastPos = fix.range[1]; 
  20. // 用拼接的字符串替換 range 內(nèi)的字符串 
  21. text += originalText.slice(Math.max(0, start, lastPos), end); 

其中比較有意思的一個點是當(dāng)兩端 range 有交集的時候:

每一個 fix 都是對一個線段(range)內(nèi)文本的修復(fù),當(dāng)有交集的時候怎么處理,這其實可以作為一個算法題來考核候選人了。

從左到右應(yīng)用 fix,然后記錄當(dāng)前的 rangeRight,應(yīng)用下一段的時候就取 rangeLeft 和上一個 rangeRight 的最大值作為 rangeLeft。

把這個問題抽象出來之后還是一個比較有意思的算法題,我覺得用來面試比較不錯,而且有真實的應(yīng)用場景。

聊回正題,fix 功能的實現(xiàn)就是對每段 range 修改的文本進(jìn)行拼接,然后替換源碼字符串就可以了。

總結(jié)

babel 和 eslint 都可以修改代碼,babel 是操作了 AST,打印代碼的時候就會生成不同的代碼,而 eslint 則是一部分 rule 支持自動 fix,當(dāng)開啟了 --fix 的時候就會自動修復(fù)。

babel 生成代碼的原理是遞歸打印 AST,拼接字符串,所以改了 AST,生成的代碼就改了。

eslint 修復(fù)代碼的邏輯是對某段 range 的文本做替換,之后拼接,這個與 AST 無關(guān),所以 eslint 的 fix 功能是可選的。

比較有意思的是 eslint 的多個 rule 返回的對多段range 的修改如何應(yīng)用到對代碼修改上,當(dāng)有交集的時候怎么辦,我覺得這個問題可以作為算法題來考查面試者了。

 

責(zé)任編輯:姜華 來源: 神光的編程秘籍
相關(guān)推薦

2011-06-13 09:59:21

2018-05-09 10:40:15

云存儲數(shù)據(jù)對象存儲

2023-05-04 07:11:29

2016-11-21 11:43:11

Python

2021-01-15 13:27:50

竊密腳本CSS惡意代碼

2014-05-16 10:44:57

設(shè)計交互設(shè)計

2021-07-09 10:29:50

云計算云計算環(huán)境云應(yīng)用

2018-04-24 11:06:18

云遷移數(shù)據(jù)遷移數(shù)據(jù)庫

2019-08-29 07:51:26

2016-12-02 10:05:49

Python彩蛋

2023-04-10 11:22:34

CIOIT運營成本

2023-03-06 14:12:47

深度學(xué)習(xí)

2016-12-06 12:48:32

開源設(shè)計

2015-06-02 16:43:21

2021-10-10 12:43:44

惡意軟件加密流量網(wǎng)絡(luò)攻擊

2019-11-20 15:09:25

安全威脅SSL加密

2013-07-29 10:02:42

2021-03-01 11:38:06

惡意軟件macOS攻擊

2015-02-28 10:52:05

2018-07-18 15:05:01

點贊
收藏

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